<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"os"

	"github.com/gonum/matrix/mat64"
)

func main() {
	// Open the sample text file
	file, err := os.Open("input.txt")
	if err != nil {
		log.Fatal(err)
	}
	//data, runesToIx, ixToRune := getDataAndVocab(file)
	data, runesToIx, _ := getDataAndVocab(file)
	file.Close()
	dataSize := len(data)
	vocabSize := len(runesToIx)
	fmt.Printf("data has %d runes, %d unique.\n", dataSize, vocabSize)

	// hyperparameters
	hiddenSize := 100
	//seqLength := 25
	//learningRate := 1e-1

	// Model parameters
	rnd := make([]float64, hiddenSize*vocabSize)
	for i := range rnd {
		rnd[i] = rand.NormFloat64()
	}
	wxh := mat64.NewDense(hiddenSize, vocabSize, rnd)
	why := mat64.NewDense(vocabSize, hiddenSize, rnd)
	rnd = make([]float64, hiddenSize*hiddenSize)
	for i := range rnd {
		rnd[i] = rand.NormFloat64() * 0.01
	}
	whh := mat64.NewDense(hiddenSize, hiddenSize, rnd)
	log.Println(wxh)
	log.Println(whh)
	log.Println(why)

}

func getDataAndVocab(input io.Reader) ([]rune, map[rune]int, map[int]rune) {
	d, err := ioutil.ReadAll(input)
	if err != nil {
		log.Fatal(err)
	}
	// Extract the rune list
	runeToIx := make(map[rune]int)
	data := bytes.Runes(d)
	for _, v := range data {
		runeToIx[v] = 0
	}
	ixToRune := make(map[int]rune, len(runeToIx))
	i := 0
	for k := range runeToIx {
		runeToIx[k] = i
		ixToRune[i] = k
		i++
	}
	return data, runeToIx, ixToRune
}
<commit_msg>WIP in the go implementation<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"os"

	"github.com/gonum/matrix/mat64"
)

func main() {
	// Open the sample text file
	file, err := os.Open("input.txt")
	if err != nil {
		log.Fatal(err)
	}
	//data, runesToIx, ixToRune := getDataAndVocab(file)
	data, runesToIx, _ := getDataAndVocab(file)
	file.Close()
	dataSize := len(data)
	vocabSize := len(runesToIx)
	fmt.Printf("data has %d runes, %d unique.\n", dataSize, vocabSize)

	// hyperparameters
	hiddenSize := 100
	seqLength := 25
	//learningRate := 1e-1

	// Model parameters
	rnd := make([]float64, hiddenSize*vocabSize)
	for i := range rnd {
		rnd[i] = rand.NormFloat64()
	}
	// Input to hidden
	wxh := mat64.NewDense(hiddenSize, vocabSize, rnd)
	// Hidden to output
	why := mat64.NewDense(vocabSize, hiddenSize, rnd)
	rnd = make([]float64, hiddenSize*hiddenSize)
	for i := range rnd {
		rnd[i] = rand.NormFloat64() * 0.01
	}
	// Hidden to hidden
	whh := mat64.NewDense(hiddenSize, hiddenSize, rnd)
	// hidden bias
	bh := mat64.NewVector(hiddenSize, make([]float64, hiddenSize))
	by := mat64.NewVector(vocabSize, make([]float64, vocabSize))

	// p is the position in the data array
	p := 0
	// n is the iteration number
	n := 0
	// hprev is a hiddenSizex1 array of initial hidden state
	hprev := mat64.NewVector(hiddenSize, make([]float64, hiddenSize))

	for {
		if p+seqLength+1 >= len(data) || n == 0 {
			// reset RNN memory
			hprev = mat64.NewVector(hiddenSize, make([]float64, hiddenSize))
			p = 0 // go from start of data
		}
	}

}

func getDataAndVocab(input io.Reader) ([]rune, map[rune]int, map[int]rune) {
	d, err := ioutil.ReadAll(input)
	if err != nil {
		log.Fatal(err)
	}
	// Extract the rune list
	runeToIx := make(map[rune]int)
	data := bytes.Runes(d)
	for _, v := range data {
		runeToIx[v] = 0
	}
	ixToRune := make(map[int]rune, len(runeToIx))
	i := 0
	for k := range runeToIx {
		runeToIx[k] = i
		ixToRune[i] = k
		i++
	}
	return data, runeToIx, ixToRune
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	cryptorand "crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"flag"
	"github.com/Sirupsen/logrus"
	"io"
	"log"
	"net"
	"strings"
	"time"
	"github.com/hashicorp/golang-lru"
)

const (
	LETSENCRYPT_CREATE_CERTIFICATE_TIMEOUT = time.Minute
	LETSENCRYPT_PRODUCTION_API_URL         = "https://acme-v01.api.letsencrypt.org/directory"
	LETSENCRYPT_STAGING_API_URL            = "https://acme-staging.api.letsencrypt.org/directory"
	PRIVATE_KEY_BITS                       = 2048
	TRY_COUNT                              = 10
	RETRY_SLEEP                            = time.Second
)

var (
	bindTo            = flag.String("bind-to", ":443", "")
	targetPort        = flag.Int("target-port", 80, "")
	targetConnTimeout = flag.Duration("target-conn-timeout", time.Second, "")
	acmeApiUrl        = flag.String("acme-server", LETSENCRYPT_PRODUCTION_API_URL, "")
	acmeTestServer    = flag.Bool("test", false, "Use test lets encrypt server instead of <acme-server>")
	certDir           = flag.String("certificates", "certs", `Directory for save cached certificates. Set cert-dir="" for disable save certs`)
	certMemCount           = flag.Int("in-memory-cnt", 10000, "How many count of certs cache in memory for prevent parse it from file")
)

var (
	localIPs    []net.IP
	acmeService *acmeStruct
)

type stateStruct struct {
	PrivateKey *rsa.PrivateKey
}

func main() {
	var err error

	flag.Parse()

	// Init
	logrus.SetLevel(logrus.DebugLevel)
	localIPs = getLocalIPs()
	acmeService = &acmeStruct{}
	certMemCache, err = lru.New(*certMemCount)
	if err != nil {
		logrus.Errorf("Can't create memory cache:", err)
		certMemCache = nil
	}

	// init service
	acmeService = &acmeStruct{}
	if *acmeTestServer {
		acmeService.serverAddress = LETSENCRYPT_STAGING_API_URL
	} else {
		acmeService.serverAddress = *acmeApiUrl
	}
	logrus.Info("Generate private keys")
	acmeService.privateKey, err = rsa.GenerateKey(cryptorand.Reader, PRIVATE_KEY_BITS)
	if err != nil {
		logrus.Panic("Can't generate private key")
	}
	acmeService.Init()
	acmeService.RegisterEnsure(context.TODO())

	// Start listen
	tcpAddr, err := net.ResolveTCPAddr("tcp", *bindTo)
	if err != nil {
		logrus.Panicf("Can't resolve bind-to address '%v': %v", *bindTo, err)
	}
	logrus.Errorf("Start listen: %v", tcpAddr)

	listener, err := net.ListenTCP("tcp", tcpAddr)
	logrus.Debug(listener.Addr())
	if err != nil {
		panic(err)
	}
	for {
		tcpConn, err := listener.AcceptTCP()
		if err != nil {
			panic(err)
		}
		go handleTcpConnection(tcpConn)
	}
}

func certificateGet(clientHello *tls.ClientHelloInfo) (cert *tls.Certificate, err error) {
	domain := strings.ToLower(clientHello.ServerName)
	if logrus.GetLevel() >= logrus.DebugLevel {
		logrus.Debugf("Required certificate for domain '%v'", domain)
	}

	if strings.HasSuffix(domain, ACME_DOMAIN_SUFFIX) {
		// force generate new certificate, without caching.
		return acmeService.CreateCertificate(domain)
	}

	cert = certificateCacheGet(domain)

	switch {
	case cert != nil && cert.Leaf.NotAfter.Before(time.Now()):
		logrus.Warnf("Expired certificate got from cache for domain '%v'", domain)
		// pass to create new certificate.
	case cert != nil:
		return cert, nil
	default:
		// pass
	}

	cert, err = acmeService.CreateCertificate(domain)
	if err == nil {
		certificateCachePut(domain, cert)
	}
	return cert, err
}

func handleTcpConnection(in *net.TCPConn) {
	target, err := getTargetConn(in)
	if err != nil {
		logrus.Errorf("Can't get target IP/port for '%v': %v", target.String(), err)
		return
	}

	// handle ssl
	tlsConfig := tls.Config{
		GetCertificate: certificateGet,
		MinVersion:     tls.VersionSSL30,
	}
	tlsConn := tls.Server(in, &tlsConfig)
	err = tlsConn.Handshake()
	logrus.Debug("tls ciper:", tlsConn.ConnectionState().CipherSuite)
	if err == nil {
		logrus.Debug("Handshake for incoming:", tlsConn.RemoteAddr().String())
	} else {
		logrus.Infof("Error in tls handshake from '%v':%v", tlsConn.RemoteAddr(), err)
	}

	startProxy(target, tlsConn)
}

func getLocalIPs() (res []net.IP) {
	bindAddr, _ := net.ResolveTCPAddr("tcp", *bindTo)
	if bindAddr.IP.IsUnspecified() || len(bindAddr.IP) == 0 {
		addresses, err := net.InterfaceAddrs()
		if err != nil {
			log.Panic("Can't get local ip addresses:", err)
		}
		res = make([]net.IP, 0, len(addresses))
		for _, addr := range addresses {
			logrus.Debug("Local ip:", addr.String())
			ip, _, err := net.ParseCIDR(addr.String())
			if err == nil {
				res = append(res, ip)
			} else {
				logrus.Errorf("Can't parse local ip '%v': %v", addr.String(), err)
			}
		}
	} else {
		res = []net.IP{bindAddr.IP}
	}
	if logrus.GetLevel() >= logrus.InfoLevel {
		ipStrings := make([]string, len(res))
		for i, addr := range res {
			ipStrings[i] = addr.String()
		}
		logrus.Info("Local ip:", ipStrings)
	}
	return res
}

func getTargetConn(in *net.TCPConn) (net.TCPAddr, error) {
	targetAddrP, err := net.ResolveTCPAddr("tcp", in.LocalAddr().String())
	if err != nil {
		logrus.Errorf("Can't resolve local addr '%v': %v", in.LocalAddr().String(), err)
		return net.TCPAddr{}, err
	}
	targetAddrP.Port = *targetPort
	return *targetAddrP, nil
}

func startProxy(targetAddr net.TCPAddr, in net.Conn) {
	logrus.Infof("Start proxy connection from '%v' to'%v'", in.RemoteAddr().String(), targetAddr.String())

	targetConnCommon, err := net.DialTimeout("tcp", targetAddr.String(), *targetConnTimeout)
	if err != nil {
		logrus.Warnf("Can't connect to target '%v': %v", targetAddr.String(), err)
		return
	}

	targetConn := targetConnCommon.(*net.TCPConn)
	go func() {
		io.Copy(in, targetConn)
		in.Close()
		targetConn.Close()
	}()
	go func() {
		io.Copy(targetConn, in)
		in.Close()
		targetConn.Close()
	}()
}
<commit_msg>fix rename certs to certificates<commit_after>package main

import (
	"context"
	cryptorand "crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"flag"
	"github.com/Sirupsen/logrus"
	"github.com/hashicorp/golang-lru"
	"io"
	"log"
	"net"
	"strings"
	"time"
)

const (
	LETSENCRYPT_CREATE_CERTIFICATE_TIMEOUT = time.Minute
	LETSENCRYPT_PRODUCTION_API_URL         = "https://acme-v01.api.letsencrypt.org/directory"
	LETSENCRYPT_STAGING_API_URL            = "https://acme-staging.api.letsencrypt.org/directory"
	PRIVATE_KEY_BITS                       = 2048
	TRY_COUNT                              = 10
	RETRY_SLEEP                            = time.Second
)

var (
	bindTo            = flag.String("bind-to", ":443", "")
	targetPort        = flag.Int("target-port", 80, "")
	targetConnTimeout = flag.Duration("target-conn-timeout", time.Second, "")
	acmeApiUrl        = flag.String("acme-server", LETSENCRYPT_PRODUCTION_API_URL, "")
	acmeTestServer    = flag.Bool("test", false, "Use test lets encrypt server instead of <acme-server>")
	certDir           = flag.String("cert-dir", "certificates", `Directory for save cached certificates. Set cert-dir="" for disable save certs`)
	certMemCount      = flag.Int("in-memory-cnt", 10000, "How many count of certs cache in memory for prevent parse it from file")
)

var (
	localIPs    []net.IP
	acmeService *acmeStruct
)

type stateStruct struct {
	PrivateKey *rsa.PrivateKey
}

func main() {
	var err error

	flag.Parse()

	// Init
	logrus.SetLevel(logrus.DebugLevel)
	localIPs = getLocalIPs()
	acmeService = &acmeStruct{}
	certMemCache, err = lru.New(*certMemCount)
	if err != nil {
		logrus.Errorf("Can't create memory cache:", err)
		certMemCache = nil
	}

	// init service
	acmeService = &acmeStruct{}
	if *acmeTestServer {
		acmeService.serverAddress = LETSENCRYPT_STAGING_API_URL
	} else {
		acmeService.serverAddress = *acmeApiUrl
	}
	logrus.Info("Generate private keys")
	acmeService.privateKey, err = rsa.GenerateKey(cryptorand.Reader, PRIVATE_KEY_BITS)
	if err != nil {
		logrus.Panic("Can't generate private key")
	}
	acmeService.Init()
	acmeService.RegisterEnsure(context.TODO())

	// Start listen
	tcpAddr, err := net.ResolveTCPAddr("tcp", *bindTo)
	if err != nil {
		logrus.Panicf("Can't resolve bind-to address '%v': %v", *bindTo, err)
	}
	logrus.Errorf("Start listen: %v", tcpAddr)

	listener, err := net.ListenTCP("tcp", tcpAddr)
	logrus.Debug(listener.Addr())
	if err != nil {
		panic(err)
	}
	for {
		tcpConn, err := listener.AcceptTCP()
		if err != nil {
			panic(err)
		}
		go handleTcpConnection(tcpConn)
	}
}

func certificateGet(clientHello *tls.ClientHelloInfo) (cert *tls.Certificate, err error) {
	domain := strings.ToLower(clientHello.ServerName)
	if logrus.GetLevel() >= logrus.DebugLevel {
		logrus.Debugf("Required certificate for domain '%v'", domain)
	}

	if strings.HasSuffix(domain, ACME_DOMAIN_SUFFIX) {
		// force generate new certificate, without caching.
		return acmeService.CreateCertificate(domain)
	}

	cert = certificateCacheGet(domain)

	switch {
	case cert != nil && cert.Leaf.NotAfter.Before(time.Now()):
		logrus.Warnf("Expired certificate got from cache for domain '%v'", domain)
		// pass to create new certificate.
	case cert != nil:
		return cert, nil
	default:
		// pass
	}

	cert, err = acmeService.CreateCertificate(domain)
	if err == nil {
		certificateCachePut(domain, cert)
	}
	return cert, err
}

func handleTcpConnection(in *net.TCPConn) {
	target, err := getTargetConn(in)
	if err != nil {
		logrus.Errorf("Can't get target IP/port for '%v': %v", target.String(), err)
		return
	}

	// handle ssl
	tlsConfig := tls.Config{
		GetCertificate: certificateGet,
		MinVersion:     tls.VersionSSL30,
	}
	tlsConn := tls.Server(in, &tlsConfig)
	err = tlsConn.Handshake()
	logrus.Debug("tls ciper:", tlsConn.ConnectionState().CipherSuite)
	if err == nil {
		logrus.Debug("Handshake for incoming:", tlsConn.RemoteAddr().String())
	} else {
		logrus.Infof("Error in tls handshake from '%v':%v", tlsConn.RemoteAddr(), err)
	}

	startProxy(target, tlsConn)
}

func getLocalIPs() (res []net.IP) {
	bindAddr, _ := net.ResolveTCPAddr("tcp", *bindTo)
	if bindAddr.IP.IsUnspecified() || len(bindAddr.IP) == 0 {
		addresses, err := net.InterfaceAddrs()
		if err != nil {
			log.Panic("Can't get local ip addresses:", err)
		}
		res = make([]net.IP, 0, len(addresses))
		for _, addr := range addresses {
			logrus.Debug("Local ip:", addr.String())
			ip, _, err := net.ParseCIDR(addr.String())
			if err == nil {
				res = append(res, ip)
			} else {
				logrus.Errorf("Can't parse local ip '%v': %v", addr.String(), err)
			}
		}
	} else {
		res = []net.IP{bindAddr.IP}
	}
	if logrus.GetLevel() >= logrus.InfoLevel {
		ipStrings := make([]string, len(res))
		for i, addr := range res {
			ipStrings[i] = addr.String()
		}
		logrus.Info("Local ip:", ipStrings)
	}
	return res
}

func getTargetConn(in *net.TCPConn) (net.TCPAddr, error) {
	targetAddrP, err := net.ResolveTCPAddr("tcp", in.LocalAddr().String())
	if err != nil {
		logrus.Errorf("Can't resolve local addr '%v': %v", in.LocalAddr().String(), err)
		return net.TCPAddr{}, err
	}
	targetAddrP.Port = *targetPort
	return *targetAddrP, nil
}

func startProxy(targetAddr net.TCPAddr, in net.Conn) {
	logrus.Infof("Start proxy connection from '%v' to'%v'", in.RemoteAddr().String(), targetAddr.String())

	targetConnCommon, err := net.DialTimeout("tcp", targetAddr.String(), *targetConnTimeout)
	if err != nil {
		logrus.Warnf("Can't connect to target '%v': %v", targetAddr.String(), err)
		return
	}

	targetConn := targetConnCommon.(*net.TCPConn)
	go func() {
		io.Copy(in, targetConn)
		in.Close()
		targetConn.Close()
	}()
	go func() {
		io.Copy(targetConn, in)
		in.Close()
		targetConn.Close()
	}()
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Arista Networks, Inc.  All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package main

import (
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
	"time"
)

var h = flag.String("header", "", "Header of the generated .go files")
var hf = flag.String("headerfile", "", "Header of the generated .go files (from the content of the file)")

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s <source_pkg> <dest_folder>\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\tsource_folder: the source folder of package to process\n")
	fmt.Fprintf(os.Stderr, "\tdest_folder  : The folder that will be created with the fake .go files\n")
	flag.PrintDefaults()
}

func main() {

	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	if len(args) != 2 {
		log.Printf("Invalid number of arguments")
		flag.Usage()
		os.Exit(1)
	}
	source := args[0]
	dest := args[1]

	// Get possible header
	header := getHeader()

	// Get "build" package info (to have the list of .go files)
	buildPkg, err := build.ImportDir(source, build.ImportComment)
	if err != nil {
		log.Fatalf("Unable to read package %s: %s", source, err)
	}

	// Create dest directory
	err = os.Mkdir(dest, 0777)
	if err != nil {
		log.Fatalf("Unable to create destination folder %s: %s", dest, err)
	}

	// Parse the list of .go source files
	for _, f := range buildPkg.GoFiles {
		writeFakeFile(path.Join(buildPkg.Dir, f), path.Join(dest, f), header, buildPkg.Name)
	}
}

var set = token.NewFileSet()

func writeFakeFile(srcFile, destFile, header, pkgName string) {
	file, err := parser.ParseFile(set, srcFile, nil, parser.ImportsOnly)
	if err != nil {
		log.Fatalf("Error reading source file %s: %s", srcFile, err)
	}
	// Write dest file
	fd, err := os.Create(destFile)
	if err != nil {
		log.Fatalf("Error creating destination file %s: %s", destFile, err)
	}

	fileInfo, err := os.Stat(srcFile)
	if err != nil {
		log.Fatalf("Unable to get stats for file %s: %s", srcFile, err)
	}

	defer onClose(fd, destFile, fileInfo.ModTime())

	if len(header) > 0 {
		fmt.Fprintf(fd, "%s\n\n", header)
	}
	fmt.Fprintf(fd, "package %s\n\n", pkgName)
	if len(file.Imports) == 0 {
		return
	}
	fmt.Fprintf(fd, "import (\n")
	for _, imp := range file.Imports {
		fmt.Fprintf(fd, "\t_ %s\n", imp.Path.Value)
	}
	fmt.Fprintf(fd, ")\n")
}

func onClose(fd *os.File, destFile string, t time.Time) {
	fd.Close()
	// Preserve the original timestamp.
	os.Chtimes(destFile, t, t)
}

func getHeader() string {
	header := ""
	if len(*h) != 0 {
		header = *h
	} else if len(*hf) != 0 {
		content, err := ioutil.ReadFile(*hf)
		if err != nil {
			log.Fatalf("Unable to read the header file %s: %s", hf, err)
		}
		header = string(content)
	}
	header = strings.Trim(header, " \t\n")

	return header
}
<commit_msg>Allow destination folder to already exist<commit_after>// Copyright (c) 2015 Arista Networks, Inc.  All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package main

import (
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
	"syscall"
	"time"
)

var h = flag.String("header", "", "Header of the generated .go files")
var hf = flag.String("headerfile", "", "Header of the generated .go files (from the content of the file)")
var allowdestexists = flag.Bool("allowdestexists", false, "Do not fail if destination folder already exists")

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s <source_pkg> <dest_folder>\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\tsource_folder: the source folder of package to process\n")
	fmt.Fprintf(os.Stderr, "\tdest_folder  : The folder that will be created with the fake .go files\n")
	flag.PrintDefaults()
}

func main() {

	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	if len(args) != 2 {
		log.Printf("Invalid number of arguments")
		flag.Usage()
		os.Exit(1)
	}
	source := args[0]
	dest := args[1]

	// Get possible header
	header := getHeader()

	// Get "build" package info (to have the list of .go files)
	buildPkg, err := build.ImportDir(source, build.ImportComment)
	if err != nil {
		log.Fatalf("Unable to read package %s: %s", source, err)
	}

	// Create dest directory
	err = os.Mkdir(dest, 0777)
	if err != nil {
		if perr, ok := err.(*os.PathError); !ok || perr.Err != syscall.EEXIST || !*allowdestexists {
			log.Fatalf("Unable to create destination folder %s: %s", dest, err)
		}
	}

	// Parse the list of .go source files
	for _, f := range buildPkg.GoFiles {
		writeFakeFile(path.Join(buildPkg.Dir, f), path.Join(dest, f), header, buildPkg.Name)
	}
}

var set = token.NewFileSet()

func writeFakeFile(srcFile, destFile, header, pkgName string) {
	file, err := parser.ParseFile(set, srcFile, nil, parser.ImportsOnly)
	if err != nil {
		log.Fatalf("Error reading source file %s: %s", srcFile, err)
	}
	// Write dest file
	fd, err := os.Create(destFile)
	if err != nil {
		log.Fatalf("Error creating destination file %s: %s", destFile, err)
	}

	fileInfo, err := os.Stat(srcFile)
	if err != nil {
		log.Fatalf("Unable to get stats for file %s: %s", srcFile, err)
	}

	defer onClose(fd, destFile, fileInfo.ModTime())

	if len(header) > 0 {
		fmt.Fprintf(fd, "%s\n\n", header)
	}
	fmt.Fprintf(fd, "package %s\n\n", pkgName)
	if len(file.Imports) == 0 {
		return
	}
	fmt.Fprintf(fd, "import (\n")
	for _, imp := range file.Imports {
		fmt.Fprintf(fd, "\t_ %s\n", imp.Path.Value)
	}
	fmt.Fprintf(fd, ")\n")
}

func onClose(fd *os.File, destFile string, t time.Time) {
	fd.Close()
	// Preserve the original timestamp.
	os.Chtimes(destFile, t, t)
}

func getHeader() string {
	header := ""
	if len(*h) != 0 {
		header = *h
	} else if len(*hf) != 0 {
		content, err := ioutil.ReadFile(*hf)
		if err != nil {
			log.Fatalf("Unable to read the header file %s: %s", hf, err)
		}
		header = string(content)
	}
	header = strings.Trim(header, " \t\n")

	return header
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/codegangsta/cli"
)

var Version string = "0.6.1"

func main() {
	newApp().Run(os.Args)
}

func newApp() *cli.App {
	app := cli.NewApp()
	app.Name = "ghq"
	app.Usage = "Manage GitHub repository clones"
	app.Version = Version
	app.Author = "motemen"
	app.Email = "motemen@gmail.com"
	app.Commands = Commands
	return app
}
<commit_msg>bump version to 0.6.2<commit_after>package main

import (
	"os"

	"github.com/codegangsta/cli"
)

var Version string = "0.6.2"

func main() {
	newApp().Run(os.Args)
}

func newApp() *cli.App {
	app := cli.NewApp()
	app.Name = "ghq"
	app.Usage = "Manage GitHub repository clones"
	app.Version = Version
	app.Author = "motemen"
	app.Email = "motemen@gmail.com"
	app.Commands = Commands
	return app
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/leaanthony/mewn"
	"github.com/pkg/browser"
	"github.com/wailsapp/wails"
)

func play()       {}
func switchMode() {}
func uninstall()  {}

func openWebsite() {
	err := browser.OpenURL("https://imperialsplendour.com/")
	print(err)
}

func version() string {
	return "2.0"
}

func main() {
	js := mewn.String("./frontend/public/build/bundle.js")
	css := mewn.String("./frontend/public/build/bundle.css")

	app := wails.CreateApp(&wails.AppConfig{
		Width:  1920,
		Height: 1200,
		Title:  "Imperial Splendour: Rise of the Republic",
		JS:     js,
		CSS:    css,
		Colour: "#131313",
	})

	app.Bind(play)
	app.Bind(switchMode)
	app.Bind(uninstall)
	app.Bind(openWebsite)
	app.Bind(&ExitCall{})
	app.Bind(version)
	app.Run()
}
<commit_msg>Implement play function<commit_after>package main

import (
	"github.com/leaanthony/mewn"
	"github.com/pkg/browser"
	"github.com/wailsapp/wails"
)

func play(exitCall *ExitCall) func() error {
	playFunc := func() error {
		err := browser.OpenURL("steam://rungameid/10500")
		if err != nil {
			return err
		}
		exitCall.Exit()
		return nil
	}
	return playFunc
}

func switchMode() {}
func uninstall()  {}

func openWebsite() {
	browser.OpenURL("https://imperialsplendour.com/")
}

func exit(exitCall *ExitCall) func() {
	exitFunc := func() {
		exitCall.Exit()
	}
	return exitFunc
}

func version() string {
	return "2.0"
}

func main() {
	js := mewn.String("./frontend/public/build/bundle.js")
	css := mewn.String("./frontend/public/build/bundle.css")

	exitCall := &ExitCall{}

	app := wails.CreateApp(&wails.AppConfig{
		Width:  1920,
		Height: 1200,
		Title:  "Imperial Splendour: Rise of the Republic",
		JS:     js,
		CSS:    css,
		Colour: "#131313",
	})

	app.Bind(play(exitCall))
	app.Bind(switchMode)
	app.Bind(uninstall)
	app.Bind(openWebsite)
	app.Bind(exit(exitCall))
	app.Bind(version)
	app.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"
	"github.com/goreleaser/goreleaser/pipeline/archive"
	"github.com/goreleaser/goreleaser/pipeline/brew"
	"github.com/goreleaser/goreleaser/pipeline/build"
	"github.com/goreleaser/goreleaser/pipeline/defaults"
	"github.com/goreleaser/goreleaser/pipeline/env"
	"github.com/goreleaser/goreleaser/pipeline/git"
	"github.com/goreleaser/goreleaser/pipeline/release"
	"github.com/goreleaser/goreleaser/pipeline/repos"
	"github.com/urfave/cli"
)

var version = "master"

var pipes = []pipeline.Pipe{
	// load data, set defaults, etc...
	defaults.Pipe{},
	env.Pipe{},
	git.Pipe{},
	repos.Pipe{},

	// real work
	build.Pipe{},
	archive.Pipe{},
	release.Pipe{},
	brew.Pipe{},
}

func main() {
	var app = cli.NewApp()
	app.Name = "release"
	app.Version = version
	app.Usage = "Deliver Go binaries as fast and easily as possible"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "config, c",
			Usage: "Load configuration from `FILE`",
			Value: "goreleaser.yml",
		},
	}
	app.Action = func(c *cli.Context) (err error) {
		var file = c.String("config")
		cfg, err := config.Load(file)
		// Allow failing to load the config file if file is not explicitly specified
		if err != nil && c.IsSet("config") {
			return cli.NewExitError(err.Error(), 1)
		}
		context := context.New(cfg)
		log.SetFlags(0)
		for _, pipe := range pipes {
			log.Println(pipe.Description())
			log.SetPrefix(" -> ")
			if err := pipe.Run(context); err != nil {
				return cli.NewExitError(err.Error(), 1)
			}
			log.SetPrefix("")
		}
		log.Println("Done!")
		return
	}
	if err := app.Run(os.Args); err != nil {
		log.Fatalln(err)
	}
}
<commit_msg>fixed name on --help<commit_after>package main

import (
	"log"
	"os"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"
	"github.com/goreleaser/goreleaser/pipeline/archive"
	"github.com/goreleaser/goreleaser/pipeline/brew"
	"github.com/goreleaser/goreleaser/pipeline/build"
	"github.com/goreleaser/goreleaser/pipeline/defaults"
	"github.com/goreleaser/goreleaser/pipeline/env"
	"github.com/goreleaser/goreleaser/pipeline/git"
	"github.com/goreleaser/goreleaser/pipeline/release"
	"github.com/goreleaser/goreleaser/pipeline/repos"
	"github.com/urfave/cli"
)

var version = "master"

var pipes = []pipeline.Pipe{
	// load data, set defaults, etc...
	defaults.Pipe{},
	env.Pipe{},
	git.Pipe{},
	repos.Pipe{},

	// real work
	build.Pipe{},
	archive.Pipe{},
	release.Pipe{},
	brew.Pipe{},
}

func main() {
	var app = cli.NewApp()
	app.Name = "goreleaser"
	app.Version = version
	app.Usage = "Deliver Go binaries as fast and easily as possible"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "config, c",
			Usage: "Load configuration from `FILE`",
			Value: "goreleaser.yml",
		},
	}
	app.Action = func(c *cli.Context) (err error) {
		var file = c.String("config")
		cfg, err := config.Load(file)
		// Allow failing to load the config file if file is not explicitly specified
		if err != nil && c.IsSet("config") {
			return cli.NewExitError(err.Error(), 1)
		}
		context := context.New(cfg)
		log.SetFlags(0)
		for _, pipe := range pipes {
			log.Println(pipe.Description())
			log.SetPrefix(" -> ")
			if err := pipe.Run(context); err != nil {
				return cli.NewExitError(err.Error(), 1)
			}
			log.SetPrefix("")
		}
		log.Println("Done!")
		return
	}
	if err := app.Run(os.Args); err != nil {
		log.Fatalln(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"net/http"
	"net/http/fcgi"
	"os"
	"path"
	"strings"
	"time"
	"strconv"

	"github.com/gin-gonic/gin"
        "github.com/brandfolder/gin-gorelic"
        "github.com/coreos/go-systemd/activation"
)

// Logger is a simple log handler, out puts in the standard of apache access log common.
// See http://httpd.apache.org/docs/2.2/logs.html#accesslog
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()
		ip, err := net.ResolveTCPAddr("tcp", c.Request.RemoteAddr)
		if err != nil {
			c.Abort()
		}

		// before request
		c.Next()
		// after request

		user := "-"
		if c.Request.URL.User != nil {
			user = c.Request.URL.User.Username()
		}

		latency := time.Since(t)

		// This is the format of Apache Log Common, with an additional field of latency
		fmt.Printf("%v - %v [%v] \"%v %v %v\" %v %v %v\n",
			ip.IP, user, t.Format(time.RFC3339), c.Request.Method, c.Request.URL.Path,
			c.Request.Proto, c.Writer.Status(), c.Request.ContentLength, latency)
	}
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func testRemoteTCPPort(address string) bool {
	_, err := net.DialTimeout("tcp", address, 3 * time.Second)
	if err != nil {
		return false
	}
	return true
}

func mainHandler(c *gin.Context) {
	fields := strings.Split(c.Params.ByName("field"), ".")
	ip, err := net.ResolveTCPAddr("tcp", c.Request.RemoteAddr)
	if err != nil {
		c.Abort()
	}

	cfIP := net.ParseIP(c.Request.Header.Get("CF-Connecting-IP"))
	if cfIP != nil {
		ip.IP = cfIP
	}

        if fields[0] == "porttest" {
		if len(fields) >= 2 {
			if port, err := strconv.Atoi(fields[1]); err == nil && port > 0 && port <= 65535 {
				c.String(200, fmt.Sprintln(testRemoteTCPPort(ip.IP.String() + ":" + fields[1])))
			} else {
				c.String(400, "Invalid Port Number")
			}
		} else {
			c.String(400, "Need Port")
		}
		return
        }

	c.Set("ip", ip.IP.String())
	c.Set("port", ip.Port)
	c.Set("ua", c.Request.UserAgent())
	c.Set("lang", c.Request.Header.Get("Accept-Language"))
	c.Set("encoding", c.Request.Header.Get("Accept-Encoding"))
	c.Set("method", c.Request.Method)
	c.Set("mime", c.Request.Header.Get("Accept"))
	c.Set("referer", c.Request.Header.Get("Referer"))
	c.Set("forwarded", c.Request.Header.Get("X-Forwarded-For"))
	c.Set("country_code", c.Request.Header.Get("CF-IPCountry"))

	ua := strings.Split(c.Request.UserAgent(), "/")

	// Only lookup hostname if the results are going to need it.
	if stringInSlice(fields[0], []string{"all", "host"}) || (fields[0] == "" && ua[0] != "curl") {
		hostnames, err := net.LookupAddr(ip.IP.String())
		if err != nil {
			c.Set("host", "")
		} else {
			c.Set("host", hostnames[0])
		}
	}

	wantsJSON := false
	if len(fields) >= 2 && fields[1] == "json" {
		wantsJSON = true
	}

	switch fields[0] {
	case "":
		//If the user is using curl, then we should just return the IP, else we show the home page.
		if ua[0] == "curl" {
			c.String(200, fmt.Sprintln(ip.IP))
		} else {
			c.HTML(200, "index.html", c.Keys)
		}
		return
	case "request":
		c.JSON(200, c.Request)
		return
	case "all":
		if wantsJSON {
			c.JSON(200, c.Keys)
		} else {
			c.String(200, "%v", c.Keys)
		}
		return
	}

	fieldResult, exists := c.Get(fields[0])
	if !exists {
		c.String(404, "Not Found")
		return
	}
	c.String(200, fmt.Sprintln(fieldResult))

}

// FileServer is a basic file serve handler, this is just here as an example.
// gin.Static() should be used instead
func FileServer(root string) gin.HandlerFunc {
	return func(c *gin.Context) {
		file := c.Params.ByName("file")
		if !strings.HasPrefix(file, "/") {
			file = "/" + file
		}
		http.ServeFile(c.Writer, c.Request, path.Join(root, path.Clean(file)))
	}
}

func main() {
	r := gin.New()
	r.Use(gin.Recovery())
	r.Use(Logger())
	r.LoadHTMLGlob("templates/*")

	if NEWRELIC_LICENSE_KEY := os.Getenv("NEWRELIC_LICENSE_KEY"); NEWRELIC_LICENSE_KEY != "" {
		var NEWRELIC_APPLICATION_NAME string
		if NEWRELIC_APPLICATION_NAME = os.Getenv("NEWRELIC_APPLICATION_NAME"); NEWRELIC_APPLICATION_NAME == "" {
			NEWRELIC_APPLICATION_NAME = "ifconfig.io"
		}
		gorelic.InitNewrelicAgent(NEWRELIC_LICENSE_KEY, NEWRELIC_APPLICATION_NAME, true)
		r.Use(gorelic.Handler)
	}

	r.GET("/:field", mainHandler)
	r.GET("/", mainHandler)

	// Create a listener for FCGI
	fcgi_listen, err := net.Listen("tcp", "127.0.0.1:4000")
	if err != nil {
		panic(err)
	}
	errc := make(chan error)
	go func(errc chan error) {
		for err := range errc {
			panic(err)
		}
	}(errc)

	go func(errc chan error) {
		errc <- fcgi.Serve(fcgi_listen, r)
	}(errc)

	// Listen on whatever systemd tells us to.
	listeners, err := activation.Listeners(true)
	if err != nil {
		fmt.Printf("Could not get systemd listerns with err %q", err)
	}
	for _, listener := range listeners {
		go func(errc chan error) {
			errc <- http.Serve(listener, r)
		}(errc)
	}

	port := os.Getenv("PORT")
	host := os.Getenv("HOST")
	if port == "" {
		port = "8080"
	}
	errc <- r.Run(host + ":" + port)
}
<commit_msg>goimports<commit_after>package main

import (
	"fmt"
	"net"
	"net/http"
	"net/http/fcgi"
	"os"
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/brandfolder/gin-gorelic"
	"github.com/coreos/go-systemd/activation"
	"github.com/gin-gonic/gin"
)

// Logger is a simple log handler, out puts in the standard of apache access log common.
// See http://httpd.apache.org/docs/2.2/logs.html#accesslog
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()
		ip, err := net.ResolveTCPAddr("tcp", c.Request.RemoteAddr)
		if err != nil {
			c.Abort()
		}

		// before request
		c.Next()
		// after request

		user := "-"
		if c.Request.URL.User != nil {
			user = c.Request.URL.User.Username()
		}

		latency := time.Since(t)

		// This is the format of Apache Log Common, with an additional field of latency
		fmt.Printf("%v - %v [%v] \"%v %v %v\" %v %v %v\n",
			ip.IP, user, t.Format(time.RFC3339), c.Request.Method, c.Request.URL.Path,
			c.Request.Proto, c.Writer.Status(), c.Request.ContentLength, latency)
	}
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func testRemoteTCPPort(address string) bool {
	_, err := net.DialTimeout("tcp", address, 3*time.Second)
	if err != nil {
		return false
	}
	return true
}

func mainHandler(c *gin.Context) {
	fields := strings.Split(c.Params.ByName("field"), ".")
	ip, err := net.ResolveTCPAddr("tcp", c.Request.RemoteAddr)
	if err != nil {
		c.Abort()
	}

	cfIP := net.ParseIP(c.Request.Header.Get("CF-Connecting-IP"))
	if cfIP != nil {
		ip.IP = cfIP
	}

	if fields[0] == "porttest" {
		if len(fields) >= 2 {
			if port, err := strconv.Atoi(fields[1]); err == nil && port > 0 && port <= 65535 {
				c.String(200, fmt.Sprintln(testRemoteTCPPort(ip.IP.String()+":"+fields[1])))
			} else {
				c.String(400, "Invalid Port Number")
			}
		} else {
			c.String(400, "Need Port")
		}
		return
	}

	c.Set("ip", ip.IP.String())
	c.Set("port", ip.Port)
	c.Set("ua", c.Request.UserAgent())
	c.Set("lang", c.Request.Header.Get("Accept-Language"))
	c.Set("encoding", c.Request.Header.Get("Accept-Encoding"))
	c.Set("method", c.Request.Method)
	c.Set("mime", c.Request.Header.Get("Accept"))
	c.Set("referer", c.Request.Header.Get("Referer"))
	c.Set("forwarded", c.Request.Header.Get("X-Forwarded-For"))
	c.Set("country_code", c.Request.Header.Get("CF-IPCountry"))

	ua := strings.Split(c.Request.UserAgent(), "/")

	// Only lookup hostname if the results are going to need it.
	if stringInSlice(fields[0], []string{"all", "host"}) || (fields[0] == "" && ua[0] != "curl") {
		hostnames, err := net.LookupAddr(ip.IP.String())
		if err != nil {
			c.Set("host", "")
		} else {
			c.Set("host", hostnames[0])
		}
	}

	wantsJSON := false
	if len(fields) >= 2 && fields[1] == "json" {
		wantsJSON = true
	}

	switch fields[0] {
	case "":
		//If the user is using curl, then we should just return the IP, else we show the home page.
		if ua[0] == "curl" {
			c.String(200, fmt.Sprintln(ip.IP))
		} else {
			c.HTML(200, "index.html", c.Keys)
		}
		return
	case "request":
		c.JSON(200, c.Request)
		return
	case "all":
		if wantsJSON {
			c.JSON(200, c.Keys)
		} else {
			c.String(200, "%v", c.Keys)
		}
		return
	}

	fieldResult, exists := c.Get(fields[0])
	if !exists {
		c.String(404, "Not Found")
		return
	}
	c.String(200, fmt.Sprintln(fieldResult))

}

// FileServer is a basic file serve handler, this is just here as an example.
// gin.Static() should be used instead
func FileServer(root string) gin.HandlerFunc {
	return func(c *gin.Context) {
		file := c.Params.ByName("file")
		if !strings.HasPrefix(file, "/") {
			file = "/" + file
		}
		http.ServeFile(c.Writer, c.Request, path.Join(root, path.Clean(file)))
	}
}

func main() {
	r := gin.New()
	r.Use(gin.Recovery())
	r.Use(Logger())
	r.LoadHTMLGlob("templates/*")

	if NEWRELIC_LICENSE_KEY := os.Getenv("NEWRELIC_LICENSE_KEY"); NEWRELIC_LICENSE_KEY != "" {
		var NEWRELIC_APPLICATION_NAME string
		if NEWRELIC_APPLICATION_NAME = os.Getenv("NEWRELIC_APPLICATION_NAME"); NEWRELIC_APPLICATION_NAME == "" {
			NEWRELIC_APPLICATION_NAME = "ifconfig.io"
		}
		gorelic.InitNewrelicAgent(NEWRELIC_LICENSE_KEY, NEWRELIC_APPLICATION_NAME, true)
		r.Use(gorelic.Handler)
	}

	r.GET("/:field", mainHandler)
	r.GET("/", mainHandler)

	// Create a listener for FCGI
	fcgi_listen, err := net.Listen("tcp", "127.0.0.1:4000")
	if err != nil {
		panic(err)
	}
	errc := make(chan error)
	go func(errc chan error) {
		for err := range errc {
			panic(err)
		}
	}(errc)

	go func(errc chan error) {
		errc <- fcgi.Serve(fcgi_listen, r)
	}(errc)

	// Listen on whatever systemd tells us to.
	listeners, err := activation.Listeners(true)
	if err != nil {
		fmt.Printf("Could not get systemd listerns with err %q", err)
	}
	for _, listener := range listeners {
		go func(errc chan error) {
			errc <- http.Serve(listener, r)
		}(errc)
	}

	port := os.Getenv("PORT")
	host := os.Getenv("HOST")
	if port == "" {
		port = "8080"
	}
	errc <- r.Run(host + ":" + port)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"

	"github.com/go-distributed/gog/agent"
	"github.com/go-distributed/gog/config"
)

func main() {
	config, err := config.ParseConfig()
	if err != nil {
		fmt.Println("Failed to parse configuration", err)
		return
	}
	ag := agent.NewAgent(config)
	ag.RegisterMessageHandler(msgCallBack)
	fmt.Printf("serving at %v...\n", config.AddrStr)
	go ag.Serve()

	if config.Peers != nil {
		if err := ag.Join(config.ShufflePeers()); err != nil {
			fmt.Println("No available peers")
			//return
		}
	}
	input := bufio.NewReader(os.Stdin)
	for {
		fmt.Println("input a message:")
		bs, err := input.ReadString('\n')
		if err != nil {
			fmt.Println("error reading:", err)
			break
		}
		if bs == "list\n" {
			ag.List()
			continue
		}
		fmt.Println(bs)
		ag.Broadcast([]byte(bs))
	}
}

func msgCallBack(msg []byte) {
	fmt.Println(string(msg))
}
<commit_msg>Remove ShufflePeers() to avoid partion in setup.<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"

	"github.com/go-distributed/gog/agent"
	"github.com/go-distributed/gog/config"
)

func main() {
	config, err := config.ParseConfig()
	if err != nil {
		fmt.Println("Failed to parse configuration", err)
		return
	}
	ag := agent.NewAgent(config)
	ag.RegisterMessageHandler(msgCallBack)
	fmt.Printf("serving at %v...\n", config.AddrStr)
	go ag.Serve()

	if config.Peers != nil {
		if err := ag.Join(config.Peers); err != nil {
			fmt.Println("No available peers")
			//return
		}
	}
	input := bufio.NewReader(os.Stdin)
	for {
		fmt.Println("input a message:")
		bs, err := input.ReadString('\n')
		if err != nil {
			fmt.Println("error reading:", err)
			break
		}
		if bs == "list\n" {
			ag.List()
			continue
		}
		fmt.Println(bs)
		ag.Broadcast([]byte(bs))
	}
}

func msgCallBack(msg []byte) {
	fmt.Println(string(msg))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"net/textproto"
	"os"
	"strings"
	"time"
)

// Connection stores messages sent in the last 30 seconds and the connection itself
type Connection struct {
	conn     net.Conn
	messages int
}

// NewConnection initialize a Connection struct
func NewConnection(conn net.Conn) Connection {
	return Connection{
		conn:     conn,
		messages: 0,
	}

}

func (connection *Connection) reduceConnectionMessages() {
	connection.messages--
}

// Message called everytime you send a message
func (connection *Connection) Message(channel string, message string) {
	fmt.Fprintf(connection.conn, "PRIVMSG %s :%s\r\n", channel, message)
	connection.messages++
	time.AfterFunc(30*time.Second, connection.reduceConnectionMessages)
}

func (bot *Bot) reduceJoins() {
	bot.joins--
}

// Bot struct for main config
type Bot struct {
	server          string
	groupserver     string
	port            string
	groupport       string
	oauth           string
	nick            string
	inconn          net.Conn
	mainconn        net.Conn
	connlist        []Connection
	groupconn       net.Conn
	groupconnactive bool
	joins           int
	toJoin          []string
}

// NewBot main config
func NewBot() *Bot {
	return &Bot{
		server:          "irc.twitch.tv",
		groupserver:     "group.tmi.twitch.tv",
		port:            "6667",
		groupport:       "6667",
		oauth:           "",
		nick:            "",
		inconn:          nil,
		mainconn:        nil,
		connlist:        make([]Connection, 0),
		groupconn:       nil,
		groupconnactive: false,
		joins:           0,
	}
}

func (bot *Bot) join(channel string) {
	if bot.joins < 42 {
		fmt.Fprintf(bot.mainconn, "JOIN %s\r\n", channel)
		bot.joins++
		time.AfterFunc(10*time.Second, bot.reduceJoins)
	}
}

// ListenToConnection listen
func (bot *Bot) ListenToConnection(conn net.Conn) {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			log.Fatal(err)
			break // break loop on errors
		}
		if strings.Contains(line, "PING ") {
			fmt.Fprintf(conn, "PONG tmi.twitch.tv\r\n")
			log.Printf("PONG tmi.twitch.tv\r\n")
		}
		bot.inconn.Write([]byte(line + "\r\n"))
	}
}

// ListenToGroupConnection validate connection is running and listen to it
func (bot *Bot) ListenToGroupConnection(conn net.Conn) {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			log.Fatal(err)
			bot.CreateGroupConnection()
			break
		}
		if strings.Contains(line, "tmi.twitch.tv 001") {
			bot.groupconnactive = true
		}
		if strings.Contains(line, "PING ") {
			fmt.Fprintf(conn, "PONG tmi.twitch.tv\r\n")
			log.Printf("PONG tmi.twitch.tv\r\n")
		}
		log.Printf(line)
		bot.inconn.Write([]byte(line + "\r\n"))
	}
}

// CreateConnection Add a new connection
func (bot *Bot) CreateConnection() (conn net.Conn, err error) {
	conn, err = net.Dial("tcp", bot.server+":"+bot.port)
	if err != nil {
		log.Fatal("unable to connect to IRC server ", err)
		return nil, err
	}
	fmt.Fprintf(conn, "PASS %s\r\n", bot.oauth)
	fmt.Fprintf(conn, "USER %s\r\n", bot.nick)
	fmt.Fprintf(conn, "NICK %s\r\n", bot.nick)
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/tags\r\n")     // enable ircv3 tags
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/commands\r\n") // enable roomstate and such
	log.Printf("new connection to IRC server %s (%s)\n", bot.server, conn.RemoteAddr())

	connnection := NewConnection(conn)
	bot.connlist = append(bot.connlist, connnection)

	if len(bot.connlist) == 1 {
		bot.mainconn = conn
	}

	go bot.ListenToConnection(conn)

	return conn, nil
}

// CreateGroupConnection creates connection to recevie and send whispers
func (bot *Bot) CreateGroupConnection() {
	conn, err := net.Dial("tcp", bot.groupserver+":"+bot.groupport)
	if err != nil {
		log.Fatal("unable to connect to IRC server ", err)
		return
	}
	fmt.Fprintf(conn, "PASS %s\r\n", bot.oauth)
	fmt.Fprintf(conn, "USER %s\r\n", bot.nick)
	fmt.Fprintf(conn, "NICK %s\r\n", bot.nick)
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/tags\r\n")     // enable ircv3 tags
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/commands\r\n") // enable roomstate and such
	log.Printf("new connection to Group IRC server %s (%s)\n", bot.groupserver, conn.RemoteAddr())

	bot.groupconn = conn

	go bot.ListenToGroupConnection(conn)
}

func main() {
	log.SetOutput(os.Stdout)
	TCPServer()
}

// Message to send a message
func (bot *Bot) Message(channel string, message string) {
	if message == "" {
		return
	}

	for i := 0; i < len(bot.connlist); i++ {
		if bot.connlist[i].messages < 90 {
			bot.connlist[i].Message(channel, message)
			return
		}
	}
	newConn, _ := bot.CreateConnection()
	fmt.Fprintf(newConn, "PRIVMSG %s :%s\r\n", channel, message)
	log.Println(newConn)
}

// Whisper to send whispers
func (bot *Bot) Whisper(username string, message string) {
	for !bot.groupconnactive {
		log.Printf("group connection not active yet")
		time.Sleep(time.Second)
	}
	fmt.Fprintf(bot.groupconn, "PRIVMSG #jtv :/w "+username+" "+message+"\r\n")
	log.Printf("/w " + username + " " + message)
}
<commit_msg>No longer "crash" the bot if a connection fucks up ;-)<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"net/textproto"
	"os"
	"strings"
	"time"
)

// Connection stores messages sent in the last 30 seconds and the connection itself
type Connection struct {
	conn     net.Conn
	messages int
}

// NewConnection initialize a Connection struct
func NewConnection(conn net.Conn) Connection {
	return Connection{
		conn:     conn,
		messages: 0,
	}

}

func (connection *Connection) reduceConnectionMessages() {
	connection.messages--
}

// Message called everytime you send a message
func (connection *Connection) Message(channel string, message string) {
	fmt.Fprintf(connection.conn, "PRIVMSG %s :%s\r\n", channel, message)
	connection.messages++
	time.AfterFunc(30*time.Second, connection.reduceConnectionMessages)
}

func (bot *Bot) reduceJoins() {
	bot.joins--
}

// Bot struct for main config
type Bot struct {
	server          string
	groupserver     string
	port            string
	groupport       string
	oauth           string
	nick            string
	inconn          net.Conn
	mainconn        net.Conn
	connlist        []Connection
	groupconn       net.Conn
	groupconnactive bool
	joins           int
	toJoin          []string
}

// NewBot main config
func NewBot() *Bot {
	return &Bot{
		server:          "irc.twitch.tv",
		groupserver:     "group.tmi.twitch.tv",
		port:            "6667",
		groupport:       "6667",
		oauth:           "",
		nick:            "",
		inconn:          nil,
		mainconn:        nil,
		connlist:        make([]Connection, 0),
		groupconn:       nil,
		groupconnactive: false,
		joins:           0,
	}
}

func (bot *Bot) join(channel string) {
	if bot.joins < 42 {
		fmt.Fprintf(bot.mainconn, "JOIN %s\r\n", channel)
		bot.joins++
		time.AfterFunc(10*time.Second, bot.reduceJoins)
	}
}

// ListenToConnection listen
func (bot *Bot) ListenToConnection(conn net.Conn) {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			log.Printf("Error reading from Connection: %s", err)
			break // break loop on errors
		}
		if strings.Contains(line, "PING ") {
			fmt.Fprintf(conn, "PONG tmi.twitch.tv\r\n")
			log.Printf("PONG tmi.twitch.tv\r\n")
		}
		bot.inconn.Write([]byte(line + "\r\n"))
	}
}

// ListenToGroupConnection validate connection is running and listen to it
func (bot *Bot) ListenToGroupConnection(conn net.Conn) {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			log.Fatal(err)
			bot.CreateGroupConnection()
			break
		}
		if strings.Contains(line, "tmi.twitch.tv 001") {
			bot.groupconnactive = true
		}
		if strings.Contains(line, "PING ") {
			fmt.Fprintf(conn, "PONG tmi.twitch.tv\r\n")
			log.Printf("PONG tmi.twitch.tv\r\n")
		}
		log.Printf(line)
		bot.inconn.Write([]byte(line + "\r\n"))
	}
}

// CreateConnection Add a new connection
func (bot *Bot) CreateConnection() (conn net.Conn, err error) {
	conn, err = net.Dial("tcp", bot.server+":"+bot.port)
	if err != nil {
		log.Fatal("unable to connect to IRC server ", err)
		return nil, err
	}
	fmt.Fprintf(conn, "PASS %s\r\n", bot.oauth)
	fmt.Fprintf(conn, "USER %s\r\n", bot.nick)
	fmt.Fprintf(conn, "NICK %s\r\n", bot.nick)
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/tags\r\n")     // enable ircv3 tags
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/commands\r\n") // enable roomstate and such
	log.Printf("new connection to IRC server %s (%s)\n", bot.server, conn.RemoteAddr())

	connnection := NewConnection(conn)
	bot.connlist = append(bot.connlist, connnection)

	if len(bot.connlist) == 1 {
		bot.mainconn = conn
	}

	go bot.ListenToConnection(conn)

	return conn, nil
}

// CreateGroupConnection creates connection to recevie and send whispers
func (bot *Bot) CreateGroupConnection() {
	conn, err := net.Dial("tcp", bot.groupserver+":"+bot.groupport)
	if err != nil {
		log.Fatal("unable to connect to IRC server ", err)
		return
	}
	fmt.Fprintf(conn, "PASS %s\r\n", bot.oauth)
	fmt.Fprintf(conn, "USER %s\r\n", bot.nick)
	fmt.Fprintf(conn, "NICK %s\r\n", bot.nick)
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/tags\r\n")     // enable ircv3 tags
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/commands\r\n") // enable roomstate and such
	log.Printf("new connection to Group IRC server %s (%s)\n", bot.groupserver, conn.RemoteAddr())

	bot.groupconn = conn

	go bot.ListenToGroupConnection(conn)
}

func main() {
	log.SetOutput(os.Stdout)
	TCPServer()
}

// Message to send a message
func (bot *Bot) Message(channel string, message string) {
	if message == "" {
		return
	}

	for i := 0; i < len(bot.connlist); i++ {
		if bot.connlist[i].messages < 90 {
			bot.connlist[i].Message(channel, message)
			return
		}
	}
	newConn, _ := bot.CreateConnection()
	fmt.Fprintf(newConn, "PRIVMSG %s :%s\r\n", channel, message)
	log.Println(newConn)
}

// Whisper to send whispers
func (bot *Bot) Whisper(username string, message string) {
	for !bot.groupconnactive {
		log.Printf("group connection not active yet")
		time.Sleep(time.Second)
	}
	fmt.Fprintf(bot.groupconn, "PRIVMSG #jtv :/w "+username+" "+message+"\r\n")
	log.Printf("/w " + username + " " + message)
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/lancetw/hcfd-forecast/db"
	"github.com/lancetw/hcfd-forecast/rain"
	"github.com/line/line-bot-sdk-go/linebot"
)

const timeZone = "Asia/Taipei"

var bot *linebot.Client

func main() {
	strID := os.Getenv("ChannelID")
	numID, err := strconv.ParseInt(strID, 10, 64)
	if err != nil {
		log.Fatal("Wrong environment setting about ChannelID")
	}
	bot, err = linebot.NewClient(numID, os.Getenv("ChannelSecret"), os.Getenv("MID"))
	if err != nil {
		log.Println("Bot:", bot, " err:", err)
	}

	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	received, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, result := range received.Results {
		content := result.Content()
		if content != nil && content.IsOperation && content.OpType == linebot.OpTypeAddedAsFriend {
			op, err := content.OperationContent()
			if err != nil {
				log.Println(err)
				return
			}
			from := op.Params[0]

			user, err := bot.GetUserProfile([]string{from})
			if err != nil {
				log.Println(err)
				return
			}
			_, err = bot.SendText([]string{from}, user.Contacts[0].DisplayName+" 您好，目前可用指令為：「加入」「退出」「雨量」「警報」「貓圖」「狀態」「時間」")
			if err != nil {
				log.Println(err)
			}
		}

		if content != nil && content.IsMessage && content.ContentType == linebot.ContentTypeText {
			user, err := bot.GetUserProfile([]string{content.From})
			if err != nil {
				return
			}
			text, err := content.TextContent()
			if err != nil {
				log.Println(err)
			}
			cmd := strings.Fields(text.Text)

			switch cmd[0] {
			case "加入":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status, addErr := c.Do("SADD", "user", content.From)
				if addErr != nil {
					log.Println("SADD to redis error", addErr, status)
				} else {
					_, err = bot.SendText([]string{content.From}, user.Contacts[0].DisplayName+" 您好，已將您加入傳送對象，未來將會傳送天氣警報資訊給您 ^＿^ ")
					if err != nil {
						log.Println(err)
					}
				}
				defer c.Close()

			case "退出":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status, setErr := c.Do("SREM", "user", content.From)
				if setErr != nil {
					log.Println("DEL to redis error", setErr, status)
				} else {
					_, err = bot.SendText([]string{content.From}, user.Contacts[0].DisplayName+" 掰掰 Q＿Q")
					if err != nil {
						log.Println(err)
					}
				}
				defer c.Close()

			case "服務":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				count, countErr := redis.Int(c.Do("SCARD", "user"))
				if countErr != nil {
					log.Println(countErr)
				} else {
					_, err = bot.SendText([]string{content.From}, fmt.Sprintf("目前有 %d 人加入自動警訊服務。", count))
					if err != nil {
						log.Println(err)
					}
				}

				defer c.Close()

			case "狀態":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status, getErr := redis.Int(c.Do("SISMEMBER", "user", content.From))
				if getErr != nil || status == 0 {
					_, err = bot.SendText([]string{content.From}, "目前沒有登記您的編號喔！")
					if err != nil {
						log.Println(err)
					}
				} else {
					_, err = bot.SendText([]string{content.From}, "您已經是傳送對象 :D")
					if err != nil {
						log.Println(err)
					}
				}
				defer c.Close()

			case "時間":
				local := time.Now()
				location, timezoneErr := time.LoadLocation(timeZone)
				if timezoneErr == nil {
					local = local.In(location)
				}
				_, err = bot.SendText([]string{content.From}, local.Format("2006/01/02 15:04:05"))
				if err != nil {
					log.Println(err)
				}

			case "雨量":
				target := []string{"新竹市"}
				if len(cmd) > 1 {
					target[0] = cmd[1]
				}

				msgs, _ := rain.GetRainingInfo(target, true)
				if len(msgs) == 0 {
					_, err = bot.SendText([]string{content.From}, "目前沒有雨量資訊！")
					if err != nil {
						log.Println(err)
					}
				} else {
					for _, msg := range msgs {
						_, err = bot.SendText([]string{content.From}, msg)
						if err != nil {
							log.Println(err)
						}
					}
				}

			case "警報":
				msgs, _ := rain.GetWarningInfo(nil)
				for _, msg := range msgs {
					_, err = bot.SendText([]string{content.From}, msg)
					if err != nil {
						log.Println(err)
					}
				}

			case "重開":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status0, clearErr0 := c.Do("DEL", "token0")
				if clearErr0 != nil {
					log.Println("DEL to redis error", clearErr0, status0)
				}
				status1, clearErr1 := c.Do("DEL", "token1")
				if clearErr1 != nil {
					log.Println("DEL to redis error", clearErr1, status1)
				}

				_, err = bot.SendText([]string{content.From}, "已重開")
				if err != nil {
					log.Println(err)
				}

			case "貓圖":
				type Cat struct {
					File string `json:"file"`
				}
				cat := new(Cat)
				getJSON("http://random.cat/meow", &cat)
				if cat.File != "" {
					_, err = bot.SendImage([]string{content.From}, cat.File, cat.File)
					if err != nil {
						log.Println(err)
					}
				}

			case "妹子":
				type MeisData struct {
					ID         string `json:"id"`
					Name       string `json:"name"`
					ImgNo      int    `json:"img_no"`
					Fanpage    int    `json:"fanpage"`
					Creator    int    `json:"creator"`
					UpdateTime string `json:"update_time"`
				}

				type Beauty struct {
					Meis map[string]MeisData `json:"meis"`
				}

				beauty := new(Beauty)
				getJSONErr := getJSON("http://beauty.zones.gamebase.com.tw/wall?json", &beauty)
				if len(beauty.Meis) > 0 {
					for fbid, data := range beauty.Meis {
						image := fmt.Sprintf("http://graph.facebook.com/%s/picture?type=large", fbid)
						_, err = bot.SendImage([]string{content.From}, image, image)
						if err != nil {
							log.Println(err)
						}

						link := fmt.Sprintf("http://graph.facebook.com/%s", data.ID)
						description := fmt.Sprintf("%s %s", data.Name, link)
						_, err = bot.SendText([]string{content.From}, description)
						if err != nil {
							log.Println(err)
						}
						_, sendRichMessageErr := bot.NewRichMessage(200).
							SetAction("MANGA", "manga", link).
							SetListener("MANGA", 0, 0, 200, 200).
							Send([]string{content.From}, image, data.Name)
						if sendRichMessageErr != nil {
							log.Println(err)
						}
						break
					}

				}

				if getJSONErr != nil {
					log.Println(getJSONErr)
				}

			default:
				_, err = bot.SendText([]string{content.From}, "指令錯誤，請重試")
				if err != nil {
					log.Println(err)
				}

			}
		}
	}
}

// getJSON func
func getJSON(url string, target interface{}) error {
	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

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

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/lancetw/hcfd-forecast/db"
	"github.com/lancetw/hcfd-forecast/rain"
	"github.com/line/line-bot-sdk-go/linebot"
)

const timeZone = "Asia/Taipei"

var bot *linebot.Client

func main() {
	strID := os.Getenv("ChannelID")
	numID, err := strconv.ParseInt(strID, 10, 64)
	if err != nil {
		log.Fatal("Wrong environment setting about ChannelID")
	}
	bot, err = linebot.NewClient(numID, os.Getenv("ChannelSecret"), os.Getenv("MID"))
	if err != nil {
		log.Println("Bot:", bot, " err:", err)
	}

	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	received, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, result := range received.Results {
		content := result.Content()
		if content != nil && content.IsOperation && content.OpType == linebot.OpTypeAddedAsFriend {
			op, err := content.OperationContent()
			if err != nil {
				log.Println(err)
				return
			}
			from := op.Params[0]

			user, err := bot.GetUserProfile([]string{from})
			if err != nil {
				log.Println(err)
				return
			}
			_, err = bot.SendText([]string{from}, user.Contacts[0].DisplayName+" 您好，目前可用指令為：「加入」「退出」「雨量」「警報」「貓圖」「狀態」「時間」")
			if err != nil {
				log.Println(err)
			}
		}

		if content != nil && content.IsMessage && content.ContentType == linebot.ContentTypeText {
			user, err := bot.GetUserProfile([]string{content.From})
			if err != nil {
				return
			}
			text, err := content.TextContent()
			if err != nil {
				log.Println(err)
			}
			cmd := strings.Fields(text.Text)

			switch cmd[0] {
			case "加入":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status, addErr := c.Do("SADD", "user", content.From)
				if addErr != nil {
					log.Println("SADD to redis error", addErr, status)
				} else {
					_, err = bot.SendText([]string{content.From}, user.Contacts[0].DisplayName+" 您好，已將您加入傳送對象，未來將會傳送天氣警報資訊給您 ^＿^ ")
					if err != nil {
						log.Println(err)
					}
				}
				defer c.Close()

			case "退出":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status, setErr := c.Do("SREM", "user", content.From)
				if setErr != nil {
					log.Println("DEL to redis error", setErr, status)
				} else {
					_, err = bot.SendText([]string{content.From}, user.Contacts[0].DisplayName+" 掰掰 Q＿Q")
					if err != nil {
						log.Println(err)
					}
				}
				defer c.Close()

			case "服務":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				count, countErr := redis.Int(c.Do("SCARD", "user"))
				if countErr != nil {
					log.Println(countErr)
				} else {
					_, err = bot.SendText([]string{content.From}, fmt.Sprintf("目前有 %d 人加入自動警訊服務。", count))
					if err != nil {
						log.Println(err)
					}
				}

				defer c.Close()

			case "狀態":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status, getErr := redis.Int(c.Do("SISMEMBER", "user", content.From))
				if getErr != nil || status == 0 {
					_, err = bot.SendText([]string{content.From}, "目前沒有登記您的編號喔！")
					if err != nil {
						log.Println(err)
					}
				} else {
					_, err = bot.SendText([]string{content.From}, "您已經是傳送對象 :D")
					if err != nil {
						log.Println(err)
					}
				}
				defer c.Close()

			case "時間":
				local := time.Now()
				location, timezoneErr := time.LoadLocation(timeZone)
				if timezoneErr == nil {
					local = local.In(location)
				}
				_, err = bot.SendText([]string{content.From}, local.Format("2006/01/02 15:04:05"))
				if err != nil {
					log.Println(err)
				}

			case "雨量":
				target := []string{"新竹市"}
				if len(cmd) > 1 {
					target[0] = cmd[1]
				}

				msgs, _ := rain.GetRainingInfo(target, true)
				if len(msgs) == 0 {
					_, err = bot.SendText([]string{content.From}, "目前沒有雨量資訊！")
					if err != nil {
						log.Println(err)
					}
				} else {
					for _, msg := range msgs {
						_, err = bot.SendText([]string{content.From}, msg)
						if err != nil {
							log.Println(err)
						}
					}
				}

			case "警報":
				msgs, _ := rain.GetWarningInfo(nil)
				for _, msg := range msgs {
					_, err = bot.SendText([]string{content.From}, msg)
					if err != nil {
						log.Println(err)
					}
				}

			case "重開":
				c := db.Connect(os.Getenv("REDISTOGO_URL"))
				status0, clearErr0 := c.Do("DEL", "token0")
				if clearErr0 != nil {
					log.Println("DEL to redis error", clearErr0, status0)
				}
				status1, clearErr1 := c.Do("DEL", "token1")
				if clearErr1 != nil {
					log.Println("DEL to redis error", clearErr1, status1)
				}

				_, err = bot.SendText([]string{content.From}, "已重開")
				if err != nil {
					log.Println(err)
				}

			case "貓圖":
				type Cat struct {
					File string `json:"file"`
				}
				cat := new(Cat)
				getJSON("http://random.cat/meow", &cat)
				if cat.File != "" {
					_, err = bot.SendImage([]string{content.From}, cat.File, cat.File)
					if err != nil {
						log.Println(err)
					}
				}

			case "妹子":
				type MeisData struct {
					ID         string `json:"id"`
					Name       string `json:"name"`
					ImgNo      int    `json:"img_no"`
					Fanpage    int    `json:"fanpage"`
					Creator    int    `json:"creator"`
					UpdateTime string `json:"update_time"`
				}

				type Beauty struct {
					Meis map[string]MeisData `json:"meis"`
				}

				beauty := new(Beauty)
				getJSONErr := getJSON("http://beauty.zones.gamebase.com.tw/wall?json", &beauty)
				if len(beauty.Meis) > 0 {
					for fbid, data := range beauty.Meis {
						image := fmt.Sprintf("http://graph.facebook.com/%s/picture?type=large", fbid)
						_, err = bot.SendImage([]string{content.From}, image, image)
						if err != nil {
							log.Println(err)
						}

						link := fmt.Sprintf("http://fb.me/%s", data.ID)
						description := fmt.Sprintf("%s %s", data.Name, link)
						_, err = bot.SendText([]string{content.From}, description)
						if err != nil {
							log.Println(err)
						}
						_, sendRichMessageErr := bot.NewRichMessage(200).
							SetAction("MANGA", "manga", image).
							SetListener("MANGA", 0, 0, 200, 200).
							Send([]string{content.From}, image, data.Name)
						if sendRichMessageErr != nil {
							log.Println(err)
						}
						break
					}

				}

				if getJSONErr != nil {
					log.Println(getJSONErr)
				}

			default:
				_, err = bot.SendText([]string{content.From}, "指令錯誤，請重試")
				if err != nil {
					log.Println(err)
				}

			}
		}
	}
}

// getJSON func
func getJSON(url string, target interface{}) error {
	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	return json.NewDecoder(r.Body).Decode(target)
}
<|endoftext|>


<commit_before>package main

import (
  "github.com/golang/crypto/acme/autocert"
  "crypto/tls"
  "log"
  "net/http"
)

func main() {

  http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
  	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
  })

  m := autocert.Manager{
  	Prompt: autocert.AcceptTOS,
  	HostPolicy: autocert.HostWhitelist("porn.kyber.space"),
  }
  s := &http.Server{
  	Addr: ":4430",
  	TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
  }
    err := s.ListenAndServeTLS(":4430", "")
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
<commit_msg>handlers, how do they work<commit_after>package main

import (
  "github.com/golang/crypto/acme/autocert"
  "crypto/tls"
  "log"
  "net/http"
  "ftm"
  "html"
)

func main() {

  http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
  	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
  })

  m := autocert.Manager{
  	Prompt: autocert.AcceptTOS,
  	HostPolicy: autocert.HostWhitelist("porn.kyber.space"),
  }
  s := &http.Server{
  	Addr: ":4430",
  	TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
  }
    err := s.ListenAndServeTLS(":4430", "")
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net"
	"net/http"

	"github.com/kayac/sqsjkr"
	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

// Default value
const (
	DefaultSocketPath = "/var/run/sqsjkr.sock"
)

// SQSJkrPlugin mackerel plugin
type SQSJkrPlugin struct {
	Tempfile string
	Socket   string
	Prefix   string
}

// GraphDefinition interface for mackerel plugin
func (sp SQSJkrPlugin) GraphDefinition() map[string](mp.Graphs) {
	return map[string]mp.Graphs{
		"stats.worker": {
			Label: "sqsjkr worker number",
			Unit:  "integer",
			Metrics: []mp.Metrics{
				mp.Metrics{Name: "idle", Label: "Idle Worker Number", Diff: false, Type: "uint32"},
				mp.Metrics{Name: "busy", Label: "Busy Worker Number", Diff: false, Type: "uint32"},
			},
		},
	}
}

// MetricKeyPrefix interface for mackerel plugin
func (sp SQSJkrPlugin) MetricKeyPrefix() string {
	return sp.Prefix
}

func fakeDial(proto, addr string) (conn net.Conn, err error) {
	return net.Dial("unix", socket)
}

// FetchMetrics interface for mackerel plugin
func (sp SQSJkrPlugin) FetchMetrics() (map[string]interface{}, error) {
	// get sqsjkr stats
	var sta sqsjkr.StatsItem
	conn, err := net.Dial("unix", sp.Socket)
	if err != nil {
		return nil, err
	}

	tr := &http.Transport{
		Dial: fakeDial,
	}
	client := &http.Client{Transport: tr}
	res, err := http.Get("http:///dummy.local/stats/metrics")
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	defer res.Body.Close()

	// decode json
	dec := json.NewDecoder(res.Body)
	if err := dec.Decode(&sta); err != nil {
		fmt.Println(err)
		return nil, err
	}

	stats := map[string]interface{}{
		"idle": sta.IdleWorkerNum,
		"busy": sta.BusyWorkerNum,
	}
	return stats, nil
}

var (
	socket  string
	tmpfile string
	prefix  string
)

func main() {
	flag.StringVar(&socket, "socket", DefaultSocketPath, "sqsjkr stats api socket path")
	flag.StringVar(&tmpfile, "tempfile", "", "tmpfile")
	flag.StringVar(&prefix, "metric-key", "sqsjkr", "tmpfile")
	flag.Parse()

	p := SQSJkrPlugin{
		Socket:   socket,
		Tempfile: tmpfile,
		Prefix:   prefix,
	}

	if p.Tempfile == "" {
		p.Tempfile = "/tmp/mackerel-plugin-sqsjkr"
	}

	helper := mp.NewMackerelPlugin(p)
	helper.Run()
}
<commit_msg>use connection with fakeDial<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net"
	"net/http"

	"github.com/kayac/sqsjkr"
	mp "github.com/mackerelio/go-mackerel-plugin-helper"
)

// Default value
const (
	DefaultSocketPath = "/var/run/sqsjkr.sock"
)

// SQSJkrPlugin mackerel plugin
type SQSJkrPlugin struct {
	Tempfile string
	Socket   string
	Prefix   string
}

// GraphDefinition interface for mackerel plugin
func (sp SQSJkrPlugin) GraphDefinition() map[string](mp.Graphs) {
	return map[string]mp.Graphs{
		"stats.worker": {
			Label: "sqsjkr worker number",
			Unit:  "integer",
			Metrics: []mp.Metrics{
				mp.Metrics{Name: "idle", Label: "Idle Worker Number", Diff: false, Type: "uint32"},
				mp.Metrics{Name: "busy", Label: "Busy Worker Number", Diff: false, Type: "uint32"},
			},
		},
	}
}

// MetricKeyPrefix interface for mackerel plugin
func (sp SQSJkrPlugin) MetricKeyPrefix() string {
	return sp.Prefix
}

func fakeDial(proto, addr string) (conn net.Conn, err error) {
	return net.Dial("unix", socket)
}

// FetchMetrics interface for mackerel plugin
func (sp SQSJkrPlugin) FetchMetrics() (map[string]interface{}, error) {
	// get sqsjkr stats
	var sta sqsjkr.StatsItem

	tr := &http.Transport{
		Dial: fakeDial,
	}
	client := &http.Client{Transport: tr}
	res, err := client.Get("http:///dummy.local/stats/metrics")
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	defer res.Body.Close()

	// decode json
	dec := json.NewDecoder(res.Body)
	if err := dec.Decode(&sta); err != nil {
		fmt.Println(err)
		return nil, err
	}

	stats := map[string]interface{}{
		"idle": sta.IdleWorkerNum,
		"busy": sta.BusyWorkerNum,
	}
	return stats, nil
}

var (
	socket  string
	tmpfile string
	prefix  string
)

func main() {
	flag.StringVar(&socket, "socket", DefaultSocketPath, "sqsjkr stats api socket path")
	flag.StringVar(&tmpfile, "tempfile", "", "tmpfile")
	flag.StringVar(&prefix, "metric-key", "sqsjkr", "tmpfile")
	flag.Parse()

	p := SQSJkrPlugin{
		Socket:   socket,
		Tempfile: tmpfile,
		Prefix:   prefix,
	}

	if p.Tempfile == "" {
		p.Tempfile = "/tmp/mackerel-plugin-sqsjkr"
	}

	helper := mp.NewMackerelPlugin(p)
	helper.Run()
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"
	"strings"

	"github.com/davecgh/go-spew/spew"
	"github.com/hashicorp/terraform/config"
)

// EvalCompareDiff is an EvalNode implementation that compares two diffs
// and errors if the diffs are not equal.
type EvalCompareDiff struct {
	Info     *InstanceInfo
	One, Two **InstanceDiff
}

// TODO: test
func (n *EvalCompareDiff) Eval(ctx EvalContext) (interface{}, error) {
	one, two := *n.One, *n.Two

	// If either are nil, let them be empty
	if one == nil {
		one = new(InstanceDiff)
		one.init()
	}
	if two == nil {
		two = new(InstanceDiff)
		two.init()
	}
	oneId, _ := one.GetAttribute("id")
	twoId, _ := two.GetAttribute("id")
	one.DelAttribute("id")
	two.DelAttribute("id")
	defer func() {
		if oneId != nil {
			one.SetAttribute("id", oneId)
		}
		if twoId != nil {
			two.SetAttribute("id", twoId)
		}
	}()

	if same, reason := one.Same(two); !same {
		spew.Config.SortKeys = true
		log.Printf("[ERROR] %s: diffs didn't match", n.Info.Id)
		log.Printf("[ERROR] %s: reason: %s", n.Info.Id, reason)
		log.Printf("[ERROR] %s: diff one: %s", n.Info.Id, spew.Sdump(one))
		log.Printf("[ERROR] %s: diff two: %s", n.Info.Id, spew.Sdump(two))
		return nil, fmt.Errorf(
			"%s: diffs didn't match during apply. This is a bug with "+
				"Terraform and should be reported as a GitHub Issue.\n"+
				"\n"+
				"Please include the following information in your report:\n"+
				"\n"+
				"    Terraform Version: %s\n"+
				"    Resource ID: %s\n"+
				"    Mismatch reason: %s\n"+
				"    Diff One (usually from plan):  %s\n"+
				"    Diff Two (usually from apply): %s\n"+
				"\n"+
				"Also include as much context as you can about your config, state, "+
				"and the steps you performed to trigger this error.\n",
			n.Info.Id, Version, n.Info.Id, reason, spew.Sdump(one), spew.Sdump(two))
	}

	return nil, nil
}

// EvalDiff is an EvalNode implementation that does a refresh for
// a resource.
type EvalDiff struct {
	Info        *InstanceInfo
	Config      **ResourceConfig
	Provider    *ResourceProvider
	Diff        **InstanceDiff
	State       **InstanceState
	OutputDiff  **InstanceDiff
	OutputState **InstanceState

	// Resource is needed to fetch the ignore_changes list so we can
	// filter user-requested ignored attributes from the diff.
	Resource *config.Resource
}

// TODO: test
func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State
	config := *n.Config
	provider := *n.Provider

	// Call pre-diff hook
	err := ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PreDiff(n.Info, state)
	})
	if err != nil {
		return nil, err
	}

	// The state for the diff must never be nil
	diffState := state
	if diffState == nil {
		diffState = new(InstanceState)
	}
	diffState.init()

	// Diff!
	diff, err := provider.Diff(n.Info, diffState, config)
	if err != nil {
		return nil, err
	}
	if diff == nil {
		diff = new(InstanceDiff)
	}

	// Preserve the DestroyTainted flag
	if n.Diff != nil {
		diff.SetTainted((*n.Diff).GetDestroyTainted())
	}

	// Require a destroy if there is an ID and it requires new.
	if diff.RequiresNew() && state != nil && state.ID != "" {
		diff.SetDestroy(true)
	}

	// If we're creating a new resource, compute its ID
	if diff.RequiresNew() || state == nil || state.ID == "" {
		var oldID string
		if state != nil {
			oldID = state.Attributes["id"]
		}

		// Add diff to compute new ID
		diff.init()
		diff.SetAttribute("id", &ResourceAttrDiff{
			Old:         oldID,
			NewComputed: true,
			RequiresNew: true,
			Type:        DiffAttrOutput,
		})
	}

	if err := n.processIgnoreChanges(diff); err != nil {
		return nil, err
	}

	// Call post-refresh hook
	err = ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PostDiff(n.Info, diff)
	})
	if err != nil {
		return nil, err
	}

	// Update our output
	*n.OutputDiff = diff

	// Update the state if we care
	if n.OutputState != nil {
		*n.OutputState = state

		// Merge our state so that the state is updated with our plan
		if !diff.Empty() && n.OutputState != nil {
			*n.OutputState = state.MergeDiff(diff)
		}
	}

	return nil, nil
}

func (n *EvalDiff) processIgnoreChanges(diff *InstanceDiff) error {
	if diff == nil || n.Resource == nil || n.Resource.Id() == "" {
		return nil
	}
	ignoreChanges := n.Resource.Lifecycle.IgnoreChanges

	if len(ignoreChanges) == 0 {
		return nil
	}

	changeType := diff.ChangeType()

	// If we're just creating the resource, we shouldn't alter the
	// Diff at all
	if changeType == DiffCreate {
		return nil
	}

	// If the resource has been tainted then we don't process ignore changes
	// since we MUST recreate the entire resource.
	if diff.DestroyTainted {
		return nil
	}

	ignorableAttrKeys := make(map[string]bool)
	for _, ignoredKey := range ignoreChanges {
		for k := range diff.CopyAttributes() {
			if ignoredKey == "*" || strings.HasPrefix(k, ignoredKey) {
				ignorableAttrKeys[k] = true
			}
		}
	}

	// If we are replacing the resource, then we expect there to be a bunch of
	// extraneous attribute diffs we need to filter out for the other
	// non-requires-new attributes going from "" -> "configval" or "" ->
	// "<computed>". Filtering these out allows us to see if we might be able to
	// skip this diff altogether.
	if changeType == DiffDestroyCreate {
		for k, v := range diff.CopyAttributes() {
			if v.Empty() || v.NewComputed {
				ignorableAttrKeys[k] = true
			}
		}

		// Here we emulate the implementation of diff.RequiresNew() with one small
		// tweak, we ignore the "id" attribute diff that gets added by EvalDiff,
		// since that was added in reaction to RequiresNew being true.
		requiresNewAfterIgnores := false
		for k, v := range diff.CopyAttributes() {
			if k == "id" {
				continue
			}
			if _, ok := ignorableAttrKeys[k]; ok {
				continue
			}
			if v.RequiresNew == true {
				requiresNewAfterIgnores = true
			}
		}

		// If we still require resource replacement after ignores, we
		// can't touch the diff, as all of the attributes will be
		// required to process the replacement.
		if requiresNewAfterIgnores {
			return nil
		}

		// Here we undo the two reactions to RequireNew in EvalDiff - the "id"
		// attribute diff and the Destroy boolean field
		log.Printf("[DEBUG] Removing 'id' diff and setting Destroy to false " +
			"because after ignore_changes, this diff no longer requires replacement")
		diff.DelAttribute("id")
		diff.SetDestroy(false)
	}

	// If we didn't hit any of our early exit conditions, we can filter the diff.
	for k := range ignorableAttrKeys {
		log.Printf("[DEBUG] [EvalIgnoreChanges] %s - Ignoring diff attribute: %s",
			n.Resource.Id(), k)
		diff.DelAttribute(k)
	}

	return nil
}

// EvalDiffDestroy is an EvalNode implementation that returns a plain
// destroy diff.
type EvalDiffDestroy struct {
	Info   *InstanceInfo
	State  **InstanceState
	Output **InstanceDiff
}

// TODO: test
func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State

	// If there is no state or we don't have an ID, we're already destroyed
	if state == nil || state.ID == "" {
		return nil, nil
	}

	// Call pre-diff hook
	err := ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PreDiff(n.Info, state)
	})
	if err != nil {
		return nil, err
	}

	// The diff
	diff := &InstanceDiff{Destroy: true}

	// Call post-diff hook
	err = ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PostDiff(n.Info, diff)
	})
	if err != nil {
		return nil, err
	}

	// Update our output
	*n.Output = diff

	return nil, nil
}

// EvalDiffDestroyModule is an EvalNode implementation that writes the diff to
// the full diff.
type EvalDiffDestroyModule struct {
	Path []string
}

// TODO: test
func (n *EvalDiffDestroyModule) Eval(ctx EvalContext) (interface{}, error) {
	diff, lock := ctx.Diff()

	// Acquire the lock so that we can do this safely concurrently
	lock.Lock()
	defer lock.Unlock()

	// Write the diff
	modDiff := diff.ModuleByPath(n.Path)
	if modDiff == nil {
		modDiff = diff.AddModule(n.Path)
	}
	modDiff.Destroy = true

	return nil, nil
}

// EvalFilterDiff is an EvalNode implementation that filters the diff
// according to some filter.
type EvalFilterDiff struct {
	// Input and output
	Diff   **InstanceDiff
	Output **InstanceDiff

	// Destroy, if true, will only include a destroy diff if it is set.
	Destroy bool
}

func (n *EvalFilterDiff) Eval(ctx EvalContext) (interface{}, error) {
	if *n.Diff == nil {
		return nil, nil
	}

	input := *n.Diff
	result := new(InstanceDiff)

	if n.Destroy {
		if input.GetDestroy() || input.RequiresNew() {
			result.SetDestroy(true)
		}
	}

	if n.Output != nil {
		*n.Output = result
	}

	return nil, nil
}

// EvalReadDiff is an EvalNode implementation that writes the diff to
// the full diff.
type EvalReadDiff struct {
	Name string
	Diff **InstanceDiff
}

func (n *EvalReadDiff) Eval(ctx EvalContext) (interface{}, error) {
	diff, lock := ctx.Diff()

	// Acquire the lock so that we can do this safely concurrently
	lock.Lock()
	defer lock.Unlock()

	// Write the diff
	modDiff := diff.ModuleByPath(ctx.Path())
	if modDiff == nil {
		return nil, nil
	}

	*n.Diff = modDiff.Resources[n.Name]

	return nil, nil
}

// EvalWriteDiff is an EvalNode implementation that writes the diff to
// the full diff.
type EvalWriteDiff struct {
	Name string
	Diff **InstanceDiff
}

// TODO: test
func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
	diff, lock := ctx.Diff()

	// The diff to write, if its empty it should write nil
	var diffVal *InstanceDiff
	if n.Diff != nil {
		diffVal = *n.Diff
	}
	if diffVal.Empty() {
		diffVal = nil
	}

	// Acquire the lock so that we can do this safely concurrently
	lock.Lock()
	defer lock.Unlock()

	// Write the diff
	modDiff := diff.ModuleByPath(ctx.Path())
	if modDiff == nil {
		modDiff = diff.AddModule(ctx.Path())
	}
	if diffVal != nil {
		modDiff.Resources[n.Name] = diffVal
	} else {
		delete(modDiff.Resources, n.Name)
	}

	return nil, nil
}
<commit_msg>Revert "[WIP] core: Log diff mismatch using spew instead of %#v"<commit_after>package terraform

import (
	"fmt"
	"log"
	"strings"

	"github.com/hashicorp/terraform/config"
)

// EvalCompareDiff is an EvalNode implementation that compares two diffs
// and errors if the diffs are not equal.
type EvalCompareDiff struct {
	Info     *InstanceInfo
	One, Two **InstanceDiff
}

// TODO: test
func (n *EvalCompareDiff) Eval(ctx EvalContext) (interface{}, error) {
	one, two := *n.One, *n.Two

	// If either are nil, let them be empty
	if one == nil {
		one = new(InstanceDiff)
		one.init()
	}
	if two == nil {
		two = new(InstanceDiff)
		two.init()
	}
	oneId, _ := one.GetAttribute("id")
	twoId, _ := two.GetAttribute("id")
	one.DelAttribute("id")
	two.DelAttribute("id")
	defer func() {
		if oneId != nil {
			one.SetAttribute("id", oneId)
		}
		if twoId != nil {
			two.SetAttribute("id", twoId)
		}
	}()

	if same, reason := one.Same(two); !same {
		log.Printf("[ERROR] %s: diffs didn't match", n.Info.Id)
		log.Printf("[ERROR] %s: reason: %s", n.Info.Id, reason)
		log.Printf("[ERROR] %s: diff one: %#v", n.Info.Id, one)
		log.Printf("[ERROR] %s: diff two: %#v", n.Info.Id, two)
		return nil, fmt.Errorf(
			"%s: diffs didn't match during apply. This is a bug with "+
				"Terraform and should be reported as a GitHub Issue.\n"+
				"\n"+
				"Please include the following information in your report:\n"+
				"\n"+
				"    Terraform Version: %s\n"+
				"    Resource ID: %s\n"+
				"    Mismatch reason: %s\n"+
				"    Diff One (usually from plan): %#v\n"+
				"    Diff Two (usually from apply): %#v\n"+
				"\n"+
				"Also include as much context as you can about your config, state, "+
				"and the steps you performed to trigger this error.\n",
			n.Info.Id, Version, n.Info.Id, reason, one, two)
	}

	return nil, nil
}

// EvalDiff is an EvalNode implementation that does a refresh for
// a resource.
type EvalDiff struct {
	Info        *InstanceInfo
	Config      **ResourceConfig
	Provider    *ResourceProvider
	Diff        **InstanceDiff
	State       **InstanceState
	OutputDiff  **InstanceDiff
	OutputState **InstanceState

	// Resource is needed to fetch the ignore_changes list so we can
	// filter user-requested ignored attributes from the diff.
	Resource *config.Resource
}

// TODO: test
func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State
	config := *n.Config
	provider := *n.Provider

	// Call pre-diff hook
	err := ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PreDiff(n.Info, state)
	})
	if err != nil {
		return nil, err
	}

	// The state for the diff must never be nil
	diffState := state
	if diffState == nil {
		diffState = new(InstanceState)
	}
	diffState.init()

	// Diff!
	diff, err := provider.Diff(n.Info, diffState, config)
	if err != nil {
		return nil, err
	}
	if diff == nil {
		diff = new(InstanceDiff)
	}

	// Preserve the DestroyTainted flag
	if n.Diff != nil {
		diff.SetTainted((*n.Diff).GetDestroyTainted())
	}

	// Require a destroy if there is an ID and it requires new.
	if diff.RequiresNew() && state != nil && state.ID != "" {
		diff.SetDestroy(true)
	}

	// If we're creating a new resource, compute its ID
	if diff.RequiresNew() || state == nil || state.ID == "" {
		var oldID string
		if state != nil {
			oldID = state.Attributes["id"]
		}

		// Add diff to compute new ID
		diff.init()
		diff.SetAttribute("id", &ResourceAttrDiff{
			Old:         oldID,
			NewComputed: true,
			RequiresNew: true,
			Type:        DiffAttrOutput,
		})
	}

	if err := n.processIgnoreChanges(diff); err != nil {
		return nil, err
	}

	// Call post-refresh hook
	err = ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PostDiff(n.Info, diff)
	})
	if err != nil {
		return nil, err
	}

	// Update our output
	*n.OutputDiff = diff

	// Update the state if we care
	if n.OutputState != nil {
		*n.OutputState = state

		// Merge our state so that the state is updated with our plan
		if !diff.Empty() && n.OutputState != nil {
			*n.OutputState = state.MergeDiff(diff)
		}
	}

	return nil, nil
}

func (n *EvalDiff) processIgnoreChanges(diff *InstanceDiff) error {
	if diff == nil || n.Resource == nil || n.Resource.Id() == "" {
		return nil
	}
	ignoreChanges := n.Resource.Lifecycle.IgnoreChanges

	if len(ignoreChanges) == 0 {
		return nil
	}

	changeType := diff.ChangeType()

	// If we're just creating the resource, we shouldn't alter the
	// Diff at all
	if changeType == DiffCreate {
		return nil
	}

	// If the resource has been tainted then we don't process ignore changes
	// since we MUST recreate the entire resource.
	if diff.DestroyTainted {
		return nil
	}

	ignorableAttrKeys := make(map[string]bool)
	for _, ignoredKey := range ignoreChanges {
		for k := range diff.CopyAttributes() {
			if ignoredKey == "*" || strings.HasPrefix(k, ignoredKey) {
				ignorableAttrKeys[k] = true
			}
		}
	}

	// If we are replacing the resource, then we expect there to be a bunch of
	// extraneous attribute diffs we need to filter out for the other
	// non-requires-new attributes going from "" -> "configval" or "" ->
	// "<computed>". Filtering these out allows us to see if we might be able to
	// skip this diff altogether.
	if changeType == DiffDestroyCreate {
		for k, v := range diff.CopyAttributes() {
			if v.Empty() || v.NewComputed {
				ignorableAttrKeys[k] = true
			}
		}

		// Here we emulate the implementation of diff.RequiresNew() with one small
		// tweak, we ignore the "id" attribute diff that gets added by EvalDiff,
		// since that was added in reaction to RequiresNew being true.
		requiresNewAfterIgnores := false
		for k, v := range diff.CopyAttributes() {
			if k == "id" {
				continue
			}
			if _, ok := ignorableAttrKeys[k]; ok {
				continue
			}
			if v.RequiresNew == true {
				requiresNewAfterIgnores = true
			}
		}

		// If we still require resource replacement after ignores, we
		// can't touch the diff, as all of the attributes will be
		// required to process the replacement.
		if requiresNewAfterIgnores {
			return nil
		}

		// Here we undo the two reactions to RequireNew in EvalDiff - the "id"
		// attribute diff and the Destroy boolean field
		log.Printf("[DEBUG] Removing 'id' diff and setting Destroy to false " +
			"because after ignore_changes, this diff no longer requires replacement")
		diff.DelAttribute("id")
		diff.SetDestroy(false)
	}

	// If we didn't hit any of our early exit conditions, we can filter the diff.
	for k := range ignorableAttrKeys {
		log.Printf("[DEBUG] [EvalIgnoreChanges] %s - Ignoring diff attribute: %s",
			n.Resource.Id(), k)
		diff.DelAttribute(k)
	}

	return nil
}

// EvalDiffDestroy is an EvalNode implementation that returns a plain
// destroy diff.
type EvalDiffDestroy struct {
	Info   *InstanceInfo
	State  **InstanceState
	Output **InstanceDiff
}

// TODO: test
func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) {
	state := *n.State

	// If there is no state or we don't have an ID, we're already destroyed
	if state == nil || state.ID == "" {
		return nil, nil
	}

	// Call pre-diff hook
	err := ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PreDiff(n.Info, state)
	})
	if err != nil {
		return nil, err
	}

	// The diff
	diff := &InstanceDiff{Destroy: true}

	// Call post-diff hook
	err = ctx.Hook(func(h Hook) (HookAction, error) {
		return h.PostDiff(n.Info, diff)
	})
	if err != nil {
		return nil, err
	}

	// Update our output
	*n.Output = diff

	return nil, nil
}

// EvalDiffDestroyModule is an EvalNode implementation that writes the diff to
// the full diff.
type EvalDiffDestroyModule struct {
	Path []string
}

// TODO: test
func (n *EvalDiffDestroyModule) Eval(ctx EvalContext) (interface{}, error) {
	diff, lock := ctx.Diff()

	// Acquire the lock so that we can do this safely concurrently
	lock.Lock()
	defer lock.Unlock()

	// Write the diff
	modDiff := diff.ModuleByPath(n.Path)
	if modDiff == nil {
		modDiff = diff.AddModule(n.Path)
	}
	modDiff.Destroy = true

	return nil, nil
}

// EvalFilterDiff is an EvalNode implementation that filters the diff
// according to some filter.
type EvalFilterDiff struct {
	// Input and output
	Diff   **InstanceDiff
	Output **InstanceDiff

	// Destroy, if true, will only include a destroy diff if it is set.
	Destroy bool
}

func (n *EvalFilterDiff) Eval(ctx EvalContext) (interface{}, error) {
	if *n.Diff == nil {
		return nil, nil
	}

	input := *n.Diff
	result := new(InstanceDiff)

	if n.Destroy {
		if input.GetDestroy() || input.RequiresNew() {
			result.SetDestroy(true)
		}
	}

	if n.Output != nil {
		*n.Output = result
	}

	return nil, nil
}

// EvalReadDiff is an EvalNode implementation that writes the diff to
// the full diff.
type EvalReadDiff struct {
	Name string
	Diff **InstanceDiff
}

func (n *EvalReadDiff) Eval(ctx EvalContext) (interface{}, error) {
	diff, lock := ctx.Diff()

	// Acquire the lock so that we can do this safely concurrently
	lock.Lock()
	defer lock.Unlock()

	// Write the diff
	modDiff := diff.ModuleByPath(ctx.Path())
	if modDiff == nil {
		return nil, nil
	}

	*n.Diff = modDiff.Resources[n.Name]

	return nil, nil
}

// EvalWriteDiff is an EvalNode implementation that writes the diff to
// the full diff.
type EvalWriteDiff struct {
	Name string
	Diff **InstanceDiff
}

// TODO: test
func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
	diff, lock := ctx.Diff()

	// The diff to write, if its empty it should write nil
	var diffVal *InstanceDiff
	if n.Diff != nil {
		diffVal = *n.Diff
	}
	if diffVal.Empty() {
		diffVal = nil
	}

	// Acquire the lock so that we can do this safely concurrently
	lock.Lock()
	defer lock.Unlock()

	// Write the diff
	modDiff := diff.ModuleByPath(ctx.Path())
	if modDiff == nil {
		modDiff = diff.AddModule(ctx.Path())
	}
	if diffVal != nil {
		modDiff.Resources[n.Name] = diffVal
	} else {
		delete(modDiff.Resources, n.Name)
	}

	return nil, nil
}
<|endoftext|>


<commit_before>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Garbage collection benchmark: parse Go packages repeatedly.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"os"
	"path"
	"runtime"
	"strings"
	"time"
)

func isGoFile(dir *os.FileInfo) bool {
	return dir.IsRegular() &&
		!strings.HasPrefix(dir.Name, ".") && // ignore .files
		path.Ext(dir.Name) == ".go"
}

func isPkgFile(dir *os.FileInfo) bool {
	return isGoFile(dir) &&
		!strings.HasSuffix(dir.Name, "_test.go") // ignore test files
}

func pkgName(filename string) string {
	file, err := parser.ParseFile(filename, nil, nil, parser.PackageClauseOnly)
	if err != nil || file == nil {
		return ""
	}
	return file.Name.Name()
}

func parseDir(dirpath string) map[string]*ast.Package {
	// the package name is the directory name within its parent
	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
	_, pkgname := path.Split(dirpath)

	// filter function to select the desired .go files
	filter := func(d *os.FileInfo) bool {
		if isPkgFile(d) {
			// Some directories contain main packages: Only accept
			// files that belong to the expected package so that
			// parser.ParsePackage doesn't return "multiple packages
			// found" errors.
			// Additionally, accept the special package name
			// fakePkgName if we are looking at cmd documentation.
			name := pkgName(dirpath + "/" + d.Name)
			return name == pkgname
		}
		return false
	}

	// get package AST
	pkgs, err := parser.ParseDir(dirpath, filter, parser.ParseComments)
	if err != nil {
		println("parse", dirpath, err.String())
		panic("fail")
	}
	return pkgs
}

func main() {
	st := &runtime.MemStats
	n := flag.Int("n", 4, "iterations")
	p := flag.Int("p", len(packages), "# of packages to keep in memory")
	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
	flag.Parse()

	var t0 int64
	pkgroot := runtime.GOROOT() + "/src/pkg/"
	for pass := 0; pass < 2; pass++ {
		// Once the heap is grown to full size, reset counters.
		// This hides the start-up pauses, which are much smaller
		// than the normal pauses and would otherwise make
		// the average look much better than it actually is.
		st.NumGC = 0
		st.PauseNs = 0
		t0 = time.Nanoseconds()

		for i := 0; i < *n; i++ {
			parsed := make([]map[string]*ast.Package, *p)
			for j := range parsed {
				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
			}
		}
		runtime.GC()
	}
	t1 := time.Nanoseconds()

	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
		st.Alloc, st.TotalAlloc,
		st.Sys,
		st.Mallocs, float64(st.PauseNs)/1e9,
		st.NumGC, float64(st.PauseNs)/1e9/float64(st.NumGC))

	fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
	for _, s := range st.BySize {
		fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
	}

	// Standard gotest benchmark output, collected by build dashboard.
	fmt.Printf("garbage.BenchmarkParser %d %d ns/op\n", *n, (t1-t0)/int64(*n))
	fmt.Printf("garbage.BenchmarkParserPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
}

var packages = []string{
	"archive/tar",
	"asn1",
	"big",
	"bufio",
	"bytes",
	"cmath",
	"compress/flate",
	"compress/gzip",
	"compress/zlib",
	"container/heap",
	"container/list",
	"container/ring",
	"container/vector",
	"crypto/aes",
	"crypto/block",
	"crypto/blowfish",
	"crypto/hmac",
	"crypto/md4",
	"crypto/md5",
	"crypto/rand",
	"crypto/rc4",
	"crypto/rsa",
	"crypto/sha1",
	"crypto/sha256",
	"crypto/sha512",
	"crypto/subtle",
	"crypto/tls",
	"crypto/x509",
	"crypto/xtea",
	"debug/dwarf",
	"debug/macho",
	"debug/elf",
	"debug/gosym",
	"debug/proc",
	"ebnf",
	"encoding/ascii85",
	"encoding/base64",
	"encoding/binary",
	"encoding/git85",
	"encoding/hex",
	"encoding/pem",
	"exec",
	"exp/datafmt",
	"exp/draw",
	"exp/eval",
	"exp/iterable",
	"expvar",
	"flag",
	"fmt",
	"go/ast",
	"go/doc",
	"go/parser",
	"go/printer",
	"go/scanner",
	"go/token",
	"gob",
	"hash",
	"hash/adler32",
	"hash/crc32",
	"hash/crc64",
	"http",
	"image",
	"image/jpeg",
	"image/png",
	"io",
	"io/ioutil",
	"json",
	"log",
	"math",
	"mime",
	"net",
	"nntp",
	"os",
	"os/signal",
	"patch",
	"path",
	"rand",
	"reflect",
	"regexp",
	"rpc",
	"runtime",
	"scanner",
	"sort",
	"strconv",
	"strings",
	"sync",
	"syscall",
	"syslog",
	"tabwriter",
	"template",
	"testing",
	"testing/iotest",
	"testing/quick",
	"testing/script",
	"time",
	"unicode",
	"utf8",
	"utf16",
	"websocket",
	"xml",
}
<commit_msg>test/garbage/parser: sync with recent parser changes<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Garbage collection benchmark: parse Go packages repeatedly.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"os"
	"path"
	"runtime"
	"strings"
	"time"
)

func isGoFile(dir *os.FileInfo) bool {
	return dir.IsRegular() &&
		!strings.HasPrefix(dir.Name, ".") && // ignore .files
		path.Ext(dir.Name) == ".go"
}

func isPkgFile(dir *os.FileInfo) bool {
	return isGoFile(dir) &&
		!strings.HasSuffix(dir.Name, "_test.go") // ignore test files
}

func pkgName(filename string) string {
	file, err := parser.ParseFile(filename, nil, parser.PackageClauseOnly)
	if err != nil || file == nil {
		return ""
	}
	return file.Name.Name
}

func parseDir(dirpath string) map[string]*ast.Package {
	// the package name is the directory name within its parent
	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
	_, pkgname := path.Split(dirpath)

	// filter function to select the desired .go files
	filter := func(d *os.FileInfo) bool {
		if isPkgFile(d) {
			// Some directories contain main packages: Only accept
			// files that belong to the expected package so that
			// parser.ParsePackage doesn't return "multiple packages
			// found" errors.
			// Additionally, accept the special package name
			// fakePkgName if we are looking at cmd documentation.
			name := pkgName(dirpath + "/" + d.Name)
			return name == pkgname
		}
		return false
	}

	// get package AST
	pkgs, err := parser.ParseDir(dirpath, filter, parser.ParseComments)
	if err != nil {
		println("parse", dirpath, err.String())
		panic("fail")
	}
	return pkgs
}

func main() {
	st := &runtime.MemStats
	n := flag.Int("n", 4, "iterations")
	p := flag.Int("p", len(packages), "# of packages to keep in memory")
	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
	flag.Parse()

	var t0 int64
	pkgroot := runtime.GOROOT() + "/src/pkg/"
	for pass := 0; pass < 2; pass++ {
		// Once the heap is grown to full size, reset counters.
		// This hides the start-up pauses, which are much smaller
		// than the normal pauses and would otherwise make
		// the average look much better than it actually is.
		st.NumGC = 0
		st.PauseNs = 0
		t0 = time.Nanoseconds()

		for i := 0; i < *n; i++ {
			parsed := make([]map[string]*ast.Package, *p)
			for j := range parsed {
				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
			}
		}
		runtime.GC()
	}
	t1 := time.Nanoseconds()

	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
		st.Alloc, st.TotalAlloc,
		st.Sys,
		st.Mallocs, float64(st.PauseNs)/1e9,
		st.NumGC, float64(st.PauseNs)/1e9/float64(st.NumGC))

	fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
	for _, s := range st.BySize {
		fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
	}

	// Standard gotest benchmark output, collected by build dashboard.
	fmt.Printf("garbage.BenchmarkParser %d %d ns/op\n", *n, (t1-t0)/int64(*n))
	fmt.Printf("garbage.BenchmarkParserPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
}

var packages = []string{
	"archive/tar",
	"asn1",
	"big",
	"bufio",
	"bytes",
	"cmath",
	"compress/flate",
	"compress/gzip",
	"compress/zlib",
	"container/heap",
	"container/list",
	"container/ring",
	"container/vector",
	"crypto/aes",
	"crypto/block",
	"crypto/blowfish",
	"crypto/hmac",
	"crypto/md4",
	"crypto/md5",
	"crypto/rand",
	"crypto/rc4",
	"crypto/rsa",
	"crypto/sha1",
	"crypto/sha256",
	"crypto/sha512",
	"crypto/subtle",
	"crypto/tls",
	"crypto/x509",
	"crypto/xtea",
	"debug/dwarf",
	"debug/macho",
	"debug/elf",
	"debug/gosym",
	"debug/proc",
	"ebnf",
	"encoding/ascii85",
	"encoding/base64",
	"encoding/binary",
	"encoding/git85",
	"encoding/hex",
	"encoding/pem",
	"exec",
	"exp/datafmt",
	"exp/draw",
	"exp/eval",
	"exp/iterable",
	"expvar",
	"flag",
	"fmt",
	"go/ast",
	"go/doc",
	"go/parser",
	"go/printer",
	"go/scanner",
	"go/token",
	"gob",
	"hash",
	"hash/adler32",
	"hash/crc32",
	"hash/crc64",
	"http",
	"image",
	"image/jpeg",
	"image/png",
	"io",
	"io/ioutil",
	"json",
	"log",
	"math",
	"mime",
	"net",
	"nntp",
	"os",
	"os/signal",
	"patch",
	"path",
	"rand",
	"reflect",
	"regexp",
	"rpc",
	"runtime",
	"scanner",
	"sort",
	"strconv",
	"strings",
	"sync",
	"syscall",
	"syslog",
	"tabwriter",
	"template",
	"testing",
	"testing/iotest",
	"testing/quick",
	"testing/script",
	"time",
	"unicode",
	"utf8",
	"utf16",
	"websocket",
	"xml",
}
<|endoftext|>