<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"path"
	"strings"
	"text/template"

	"github.com/goreleaser/goreleaser/config"
	yaml "gopkg.in/yaml.v1"
)

var tplsrc = `#!/bin/sh
set -e
#  Code generated by godownloader. DO NOT EDIT.

BINARY={{ .Build.Binary }}
FORMAT={{ .Archive.Format }}
OWNER={{ $.Release.GitHub.Owner }}
REPO={{ $.Release.GitHub.Name }}
BINDIR=${BINDIR:-./bin}

VERSION=$1
if [ -z "${VERSION}" ]; then
echo ""
echo "$0: download go binaries for ${OWNER}/${REPO}"
echo ""
echo "Usage: $0 [version]"
echo "  where [version] is 'latest' or a version number from"
echo "  https://github.com/${OWNER}/${REPO}/releases"
echo ""
echo "Generated by godownloader"
echo " https://github.com/goreleaser/godownloader"
echo ""
exit 1
fi

# download dest source
# if dest is "-", then output to stdout
# if source is api.github.com add auth token
download() {
  DEST=$1
  SOURCE=$2

  HEADER=""
  case $SOURCE in
  https://api.github.com*)
     test -z "$GITHUB_TOKEN" || HEADER="Authorization: token $GITHUB_TOKEN"
     ;;
  esac

  if which curl > /dev/null; then
    WGET="curl -sSL"
    test -z "$GITHUB_TOKEN" || WGET="${WGET} -H \"${HEADER}\""
    if [ "${DEST}" != "-" ]; then
      WGET="$WGET -o $DEST"
    fi
  elif which wget > /dev/null; then
    WGET="wget -q -O $DEST"
    test -z "$GITHUB_TOKEN" || WGET="${WGET} --header \"${HEADER}\""
  else
    echo "Unable to find wget or curl.  Exit"
    exit 1
  fi

  ${WGET} ${SOURCE}
}

if [ "${VERSION}" = "latest" ]; then
  echo "Checking GitHub for latest version of ${OWNER}/${REPO}"
  VERSION=$(download - https://api.github.com/repos/${OWNER}/${REPO}/releases/latest | grep -m 1 "\"name\":" | cut -d ":" -f 2 | tr -d ' ",')
  if [ -z "${VERSION}" ]; then
    echo "Unable to determine latest release for ${OWNER}/${REPO}"
    exit 1
   fi
fi

# if version starts with 'v', remove it
VERSION=${VERSION#v}

OS=$(uname -s)
ARCH=$(uname -m)

# change format (tar.gz or zip) based on ARCH
{{- with .Archive.FormatOverrides }}
case ${ARCH} in
{{- range . }}
{{ .Goos }}) FORMAT={{ .Format }} ;;
esac
{{- end }}
{{- end }}

# adjust archive name based on OS
{{- with .Archive.Replacements }}
case ${OS} in
{{- range $k, $v := . }}
{{ $k }}) OS={{ $v }} ;;
{{- end }}
esac

# adjust archive name based on ARCH
case ${ARCH} in
{{- range $k, $v := . }}
{{ $k }}) ARCH={{ $v }} ;;
{{- end }}
esac
{{- end }}

{{ .Archive.NameTemplate }}
TARBALL=${NAME}.${FORMAT}
URL=https://github.com/${OWNER}/${REPO}/releases/download/v${VERSION}/${TARBALL}

# Destructive operations start here
#
#
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
mkdir -p ${TMPDIR}
rm -f ${TMPDIR}/${TARBALL}
download ${TMPDIR}/${TARBALL} ${URL}
tar -C ${TMPDIR} -xzf ${TMPDIR}/${TARBALL}
install -d ${BINDIR}
install ${TMPDIR}/${BINARY} ${BINDIR}/
`

func makeShell(cfg *config.Project) (string, error) {
	var out bytes.Buffer
	t, err := template.New("shell").Parse(tplsrc)
	if err != nil {
		return "", err
	}
	err = t.Execute(&out, cfg)
	return out.String(), err
}

// converts the given name template to it's equivalent in shell
// except for the default goreleaser templates, templates with
// conditionals will return an error
//
// {{ .Binary }} --->  NAME=${BINARY}, etc.
//
func makeName(target string) (string, error) {
	prefix := ""
	// TODO: error on conditionals
	if target == "" || target == "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" {
		prefix = "if [ ! -z \"${ARM}\" ]; then ARM=\"v$ARM\"; fi"
		target = "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ .Arm }}"
	}
	var varmap = map[string]string{
		"Os":      "${OS}",
		"Arch":    "${ARCH}",
		"Arm":     "${ARM}",
		"Version": "${VERSION}",
		"Tag":     "${TAG}",
		"Binary":  "${BINARY}",
	}

	var out bytes.Buffer
	if prefix != "" {
		out.WriteString(prefix + "\n")
	}
	out.WriteString("NAME=")
	t, err := template.New("name").Parse(target)
	if err != nil {
		return "", err
	}
	err = t.Execute(&out, varmap)
	return out.String(), err
}

func readURL(loc string) ([]byte, error) {
	resp, err := http.Get(loc)
	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)

	// to make errcheck be happy
	errc := resp.Body.Close()
	if err != nil {
		return nil, err
	}
	if errc != nil {
		return nil, errc
	}
	return body, err
}

func Load(repo string, file string) (*config.Project, error) {
	if repo == "" && file == "" {
		return nil, fmt.Errorf("Need a repo or file")
	}
	if file == "" {
		file = "https://raw.githubusercontent.com/" + repo + "/master/goreleaser.yml"
	}
	var body []byte
	var err error
	log.Printf("Reading %s", file)
	if strings.HasPrefix(file, "http") {
		body, err = readURL(file)
	} else {
		body, err = ioutil.ReadFile(file)
	}
	if err != nil {
		return nil, err
	}
	project := &config.Project{}
	err = yaml.Unmarshal(body, project)
	if err != nil {
		return nil, err
	}

	// if not specified add in GitHub owner/repo info
	if project.Release.GitHub.Owner == "" {
		if repo == "" {
			return nil, fmt.Errorf("Need to provide owner/name repo!")
		}
		project.Release.GitHub.Owner = path.Dir(repo)
		project.Release.GitHub.Name = path.Base(repo)
	}

	// set default archive format
	if project.Archive.Format == "" {
		project.Archive.Format = "tar.gz"
	}

	// set default binary name
	if project.Build.Binary == "" {
		project.Build.Binary = path.Base(repo)
	}

	// Convert replacements from GOOS/GOARCH to uname.

	// map of golang OS/ARCH identifier to what uname uses
	uname := map[string]string{
		"darwin":  "Darwin",
		"linux":   "Linux",
		"freebsd": "FreeBSD",
		"openbsd": "OpenBSD",
		"netbsd":  "NetBSD",
		"windows": "Windows",
		"386":     "i386",
		"amd64":   "x86_64",
	}
	rmap := make(map[string]string)
	for k, v := range project.Archive.Replacements {
		newk := uname[k]

		// if unknown, keep
		if newk == "" {
			rmap[k] = v
			continue
		}

		// if mapping is an idenity, then ignore
		if newk == v {
			continue
		}

		rmap[newk] = v
	}
	project.Archive.Replacements = rmap

	// do something similar for format over-rides
	for i := 0; i < len(project.Archive.FormatOverrides); i++ {
		goos := project.Archive.FormatOverrides[i].Goos
		newos := uname[goos]
		if newos != "" {
			project.Archive.FormatOverrides[i].Goos = newos
		}
	}
	return project, nil
}

func main() {
	repo := flag.String("repo", "", "owner/name of repository")
	flag.Parse()
	args := flag.Args()
	file := ""
	if len(args) > 0 {
		file = args[0]
	}
	cfg, err := Load(*repo, file)
	if err != nil {
		log.Fatalf("Unable to parse: %s", err)
	}

	// get name template
	name, err := makeName(cfg.Archive.NameTemplate)
	cfg.Archive.NameTemplate = name
	if err != nil {
		log.Fatalf("Unable generate name: %s", err)
	}

	shell, err := makeShell(cfg)
	if err != nil {
		log.Fatalf("Unable to generate shell: %s", err)
	}
	fmt.Println(shell)
}
<commit_msg>Close #3 zip file support<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"path"
	"strings"
	"text/template"

	"github.com/goreleaser/goreleaser/config"
	yaml "gopkg.in/yaml.v1"
)

var tplsrc = `#!/bin/sh
set -e
#  Code generated by godownloader. DO NOT EDIT.

BINARY={{ .Build.Binary }}
FORMAT={{ .Archive.Format }}
OWNER={{ $.Release.GitHub.Owner }}
REPO={{ $.Release.GitHub.Name }}
BINDIR=${BINDIR:-./bin}

VERSION=$1
if [ -z "${VERSION}" ]; then
echo ""
echo "$0: download go binaries for ${OWNER}/${REPO}"
echo ""
echo "Usage: $0 [version]"
echo "  where [version] is 'latest' or a version number from"
echo "  https://github.com/${OWNER}/${REPO}/releases"
echo ""
echo "Generated by godownloader"
echo " https://github.com/goreleaser/godownloader"
echo ""
exit 1
fi

# download dest source
# if dest is "-", then output to stdout
# if source is api.github.com add auth token
download() {
  DEST=$1
  SOURCE=$2

  HEADER=""
  case $SOURCE in
  https://api.github.com*)
     test -z "$GITHUB_TOKEN" || HEADER="Authorization: token $GITHUB_TOKEN"
     ;;
  esac

  if which curl > /dev/null; then
    WGET="curl -sSL"
    test -z "$GITHUB_TOKEN" || WGET="${WGET} -H \"${HEADER}\""
    if [ "${DEST}" != "-" ]; then
      WGET="$WGET -o $DEST"
    fi
  elif which wget > /dev/null; then
    WGET="wget -q -O $DEST"
    test -z "$GITHUB_TOKEN" || WGET="${WGET} --header \"${HEADER}\""
  else
    echo "Unable to find wget or curl.  Exit"
    exit 1
  fi

  ${WGET} ${SOURCE}
}

if [ "${VERSION}" = "latest" ]; then
  echo "Checking GitHub for latest version of ${OWNER}/${REPO}"
  VERSION=$(download - https://api.github.com/repos/${OWNER}/${REPO}/releases/latest | grep -m 1 "\"name\":" | cut -d ":" -f 2 | tr -d ' ",')
  if [ -z "${VERSION}" ]; then
    echo "Unable to determine latest release for ${OWNER}/${REPO}"
    exit 1
   fi
fi

# if version starts with 'v', remove it
VERSION=${VERSION#v}

OS=$(uname -s)
ARCH=$(uname -m)

# change format (tar.gz or zip) based on ARCH
{{- with .Archive.FormatOverrides }}
case ${ARCH} in
{{- range . }}
{{ .Goos }}) FORMAT={{ .Format }} ;;
esac
{{- end }}
{{- end }}

# adjust archive name based on OS
{{- with .Archive.Replacements }}
case ${OS} in
{{- range $k, $v := . }}
{{ $k }}) OS={{ $v }} ;;
{{- end }}
esac

# adjust archive name based on ARCH
case ${ARCH} in
{{- range $k, $v := . }}
{{ $k }}) ARCH={{ $v }} ;;
{{- end }}
esac
{{- end }}

{{ .Archive.NameTemplate }}
TARBALL=${NAME}.${FORMAT}
URL=https://github.com/${OWNER}/${REPO}/releases/download/v${VERSION}/${TARBALL}

# Destructive operations start here
#
#
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
mkdir -p ${TMPDIR}
rm -f ${TMPDIR}/${TARBALL}
download ${TMPDIR}/${TARBALL} ${URL}
case ${FORMAT} in
  tar.gz)
   tar -C ${TMPDIR} -xzf ${TMPDIR}/${TARBALL}
   ;;
  zip)
   (cd ${TMPDIR} && unzip ${TARBALL})
   ;;
  *)
   echo "unknown format '${FORMAT}' - exiting"
   exit 1
   ;;
esac
install -d ${BINDIR}
install ${TMPDIR}/${BINARY} ${BINDIR}/
`

func makeShell(cfg *config.Project) (string, error) {
	var out bytes.Buffer
	t, err := template.New("shell").Parse(tplsrc)
	if err != nil {
		return "", err
	}
	err = t.Execute(&out, cfg)
	return out.String(), err
}

// converts the given name template to it's equivalent in shell
// except for the default goreleaser templates, templates with
// conditionals will return an error
//
// {{ .Binary }} --->  NAME=${BINARY}, etc.
//
func makeName(target string) (string, error) {
	prefix := ""
	// TODO: error on conditionals
	if target == "" || target == "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" {
		prefix = "if [ ! -z \"${ARM}\" ]; then ARM=\"v$ARM\"; fi"
		target = "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ .Arm }}"
	}
	var varmap = map[string]string{
		"Os":      "${OS}",
		"Arch":    "${ARCH}",
		"Arm":     "${ARM}",
		"Version": "${VERSION}",
		"Tag":     "${TAG}",
		"Binary":  "${BINARY}",
	}

	var out bytes.Buffer
	if prefix != "" {
		out.WriteString(prefix + "\n")
	}
	out.WriteString("NAME=")
	t, err := template.New("name").Parse(target)
	if err != nil {
		return "", err
	}
	err = t.Execute(&out, varmap)
	return out.String(), err
}

func readURL(loc string) ([]byte, error) {
	resp, err := http.Get(loc)
	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)

	// to make errcheck be happy
	errc := resp.Body.Close()
	if err != nil {
		return nil, err
	}
	if errc != nil {
		return nil, errc
	}
	return body, err
}

func Load(repo string, file string) (*config.Project, error) {
	if repo == "" && file == "" {
		return nil, fmt.Errorf("Need a repo or file")
	}
	if file == "" {
		file = "https://raw.githubusercontent.com/" + repo + "/master/goreleaser.yml"
	}
	var body []byte
	var err error
	log.Printf("Reading %s", file)
	if strings.HasPrefix(file, "http") {
		body, err = readURL(file)
	} else {
		body, err = ioutil.ReadFile(file)
	}
	if err != nil {
		return nil, err
	}
	project := &config.Project{}
	err = yaml.Unmarshal(body, project)
	if err != nil {
		return nil, err
	}

	// if not specified add in GitHub owner/repo info
	if project.Release.GitHub.Owner == "" {
		if repo == "" {
			return nil, fmt.Errorf("Need to provide owner/name repo!")
		}
		project.Release.GitHub.Owner = path.Dir(repo)
		project.Release.GitHub.Name = path.Base(repo)
	}

	// set default archive format
	if project.Archive.Format == "" {
		project.Archive.Format = "tar.gz"
	}

	// set default binary name
	if project.Build.Binary == "" {
		project.Build.Binary = path.Base(repo)
	}

	// Convert replacements from GOOS/GOARCH to uname.

	// map of golang OS/ARCH identifier to what uname uses
	uname := map[string]string{
		"darwin":  "Darwin",
		"linux":   "Linux",
		"freebsd": "FreeBSD",
		"openbsd": "OpenBSD",
		"netbsd":  "NetBSD",
		"windows": "Windows",
		"386":     "i386",
		"amd64":   "x86_64",
	}
	rmap := make(map[string]string)
	for k, v := range project.Archive.Replacements {
		newk := uname[k]

		// if unknown, keep
		if newk == "" {
			rmap[k] = v
			continue
		}

		// if mapping is an idenity, then ignore
		if newk == v {
			continue
		}

		rmap[newk] = v
	}
	project.Archive.Replacements = rmap

	// do something similar for format over-rides
	for i := 0; i < len(project.Archive.FormatOverrides); i++ {
		goos := project.Archive.FormatOverrides[i].Goos
		newos := uname[goos]
		if newos != "" {
			project.Archive.FormatOverrides[i].Goos = newos
		}
	}
	return project, nil
}

func main() {
	repo := flag.String("repo", "", "owner/name of repository")
	flag.Parse()
	args := flag.Args()
	file := ""
	if len(args) > 0 {
		file = args[0]
	}
	cfg, err := Load(*repo, file)
	if err != nil {
		log.Fatalf("Unable to parse: %s", err)
	}

	// get name template
	name, err := makeName(cfg.Archive.NameTemplate)
	cfg.Archive.NameTemplate = name
	if err != nil {
		log.Fatalf("Unable generate name: %s", err)
	}

	shell, err := makeShell(cfg)
	if err != nil {
		log.Fatalf("Unable to generate shell: %s", err)
	}
	fmt.Println(shell)
}
<|endoftext|>


<commit_before>package main // import "github.com/Jimdo/asg-ebs"

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"

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

type AsgEbs struct {
	AwsConfig        *aws.Config
	Region           string
	AvailabilityZone string
	InstanceId       string
}

func NewAsgEbs() *AsgEbs {
	asgEbs := &AsgEbs{}

	metadata := ec2metadata.New(session.New())

	region, err := metadata.Region()
	if err != nil {
		log.Fatal("Failed to get region from instance metadata", err)
	}
	log.Print("Setting region to " + region)
	asgEbs.Region = region

	availabilityZone, err := metadata.GetMetadata("placement/availability-zone")
	if err != nil {
		log.Fatal("Failed to get availability zone from instance metadata", err)
	}
	log.Print("Setting availability zone to " + availabilityZone)
	asgEbs.AvailabilityZone = availabilityZone

	instanceId, err := metadata.GetMetadata("instance-id")
	if err != nil {
		log.Fatal("Failed to get instance id from instance metadata", err)
	}
	log.Print("Setting instance id to " + instanceId)
	asgEbs.InstanceId = instanceId

	asgEbs.AwsConfig = aws.NewConfig().
		WithRegion(region).
		WithCredentials(ec2rolecreds.NewCredentials(session.New()))

	return asgEbs
}

func (asgEbs *AsgEbs) findVolume(tagKey string, tagValue string) (*string, error) {
	svc := ec2.New(session.New(asgEbs.AwsConfig))

	params := &ec2.DescribeVolumesInput{
		Filters: []*ec2.Filter{
			{
				Name: aws.String("tag:" + tagKey),
				Values: []*string{
					aws.String(tagValue),
				},
			},
			{
				Name: aws.String("status"),
				Values: []*string{
					aws.String("available"),
				},
			},
			{
				Name: aws.String("availability-zone"),
				Values: []*string{
					aws.String(asgEbs.AvailabilityZone),
				},
			},
		},
	}

	describeVolumesOutput, err := svc.DescribeVolumes(params)
	if err != nil {
		return nil, err
	}
	if len(describeVolumesOutput.Volumes) == 0 {
		return nil, nil
	}
	return describeVolumesOutput.Volumes[0].VolumeId, nil
}

func (asgEbs *AsgEbs) createVolume(createSize int64, createName string, createVolumeType string, createTags map[string]string) (*string, error) {
	svc := ec2.New(session.New(asgEbs.AwsConfig))

	createVolumeInput := &ec2.CreateVolumeInput{
		AvailabilityZone: &asgEbs.AvailabilityZone,
		Size:             aws.Int64(createSize),
		VolumeType:       aws.String(createVolumeType),
	}
	vol, err := svc.CreateVolume(createVolumeInput)
	if err != nil {
		return nil, err
	}
	tags := []*ec2.Tag{
		{
			Key:   aws.String("Name"),
			Value: aws.String(createName),
		},
	}
	for k, v := range createTags {
		tags = append(tags,
			&ec2.Tag{
				Key:   aws.String(k),
				Value: aws.String(v),
			},
		)
	}

	createTagsInput := &ec2.CreateTagsInput{
		Resources: []*string{vol.VolumeId},
		Tags:      tags,
	}
	_, err = svc.CreateTags(createTagsInput)
	if err != nil {
		return vol.VolumeId, err
	}

	describeVolumeInput := &ec2.DescribeVolumesInput{
		VolumeIds: []*string{vol.VolumeId},
	}
	err = svc.WaitUntilVolumeAvailable(describeVolumeInput)
	if err != nil {
		return vol.VolumeId, err
	}
	return vol.VolumeId, nil
}

func (asgEbs *AsgEbs) attachVolume(volumeId string, attachAs string) error {
	svc := ec2.New(session.New(asgEbs.AwsConfig))

	attachVolumeInput := &ec2.AttachVolumeInput{
		VolumeId:   aws.String(volumeId),
		Device:     aws.String(attachAs),
		InstanceId: aws.String(asgEbs.InstanceId),
	}
	_, err := svc.AttachVolume(attachVolumeInput)
	if err != nil {
		return err
	}

	describeVolumeInput := &ec2.DescribeVolumesInput{
		VolumeIds: []*string{aws.String(volumeId)},
	}
	err = svc.WaitUntilVolumeInUse(describeVolumeInput)
	if err != nil {
		return err
	}

	return nil
}

type CreateTagsValue map[string]string

func (v CreateTagsValue) Set(str string) error {
	parts := strings.SplitN(str, "=", 2)
	if len(parts) != 2 {
		return fmt.Errorf("expected KEY=VALUE got '%s'", str)
	}
	key := parts[0]
	value := parts[1]
	v[key] = value
	return nil
}

func (v CreateTagsValue) String() string {
	return ""
}

func CreateTags(s kingpin.Settings) (target *map[string]string) {
	newMap := make(map[string]string)
	target = &newMap
	s.SetValue((*CreateTagsValue)(target))
	return
}

func main() {
	var (
		tagKey           = kingpin.Flag("tag-key", "The tag key to search for").Required().PlaceHolder("KEY").String()
		tagValue         = kingpin.Flag("tag-value", "The tag value to search for").Required().PlaceHolder("VALUE").String()
		attachAs         = kingpin.Flag("attach-as", "device name e.g. xvdb").Required().PlaceHolder("DEVICE").String()
		create           = kingpin.Flag("create", "Create volume if no volume is available").Bool()
		createSize       = kingpin.Flag("create-size", "The size of the created volume, in GiBs").PlaceHolder("SIZE").Int64()
		createName       = kingpin.Flag("create-name", "The name of the created volume").PlaceHolder("NAME").String()
		createVolumeType = kingpin.Flag("create-volume-type", "The volume type of the created volume. This can be `gp2` for General Purpose (SSD) volumes or `standard` for Magnetic volumes").PlaceHolder("TYPE").Enum("standard", "gp2")
		createTags       = CreateTags(kingpin.Flag("create-tags", "Tag to use for the new volume, can be specified multiple times").PlaceHolder("KEY=VALUE"))
	)

	kingpin.UsageTemplate(kingpin.CompactUsageTemplate)
	kingpin.CommandLine.Help = "Script to attach an EBS Volume to an EC2 instance and optionally create it"
	kingpin.Parse()

	if *create {
		if *createSize == 0 {
			kingpin.Fatalf("required flag --create-size not provided")
		}
		if *createName == "" {
			kingpin.Fatalf("required flag --create-name not provided")
		}
		if *createVolumeType == "" {
			kingpin.Fatalf("required flag --create-volume-type not provided")
		}
	}

	asgEbs := NewAsgEbs()

	volume, err := asgEbs.findVolume(*tagKey, *tagValue)
	if err != nil {
		log.Fatal("Failed to find volumes", err)
	}

	if volume == nil {
		if *create {
			log.Print("Creating new volume")
			volume, err = asgEbs.createVolume(*createSize, *createName, *createVolumeType, *createTags)
			if err != nil {
				log.Fatal("Failed to create new volume", err)
			}
		} else {
			log.Print("No available volume can be found")
			os.Exit(2)
		}
	}

	log.Print("Attaching volume ", *volume)
	err = asgEbs.attachVolume(*volume, *attachAs)
	if err != nil {
		log.Fatal("Failed to attach volume", err)
	}

	os.Exit(0)
}
<commit_msg>Create filesystem after creating volume<commit_after>package main // import "github.com/Jimdo/asg-ebs"

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"

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

type AsgEbs struct {
	AwsConfig        *aws.Config
	Region           string
	AvailabilityZone string
	InstanceId       string
}

func NewAsgEbs() *AsgEbs {
	asgEbs := &AsgEbs{}

	metadata := ec2metadata.New(session.New())

	region, err := metadata.Region()
	if err != nil {
		log.Fatal("Failed to get region from instance metadata", err)
	}
	log.Print("Setting region to " + region)
	asgEbs.Region = region

	availabilityZone, err := metadata.GetMetadata("placement/availability-zone")
	if err != nil {
		log.Fatal("Failed to get availability zone from instance metadata", err)
	}
	log.Print("Setting availability zone to " + availabilityZone)
	asgEbs.AvailabilityZone = availabilityZone

	instanceId, err := metadata.GetMetadata("instance-id")
	if err != nil {
		log.Fatal("Failed to get instance id from instance metadata", err)
	}
	log.Print("Setting instance id to " + instanceId)
	asgEbs.InstanceId = instanceId

	asgEbs.AwsConfig = aws.NewConfig().
		WithRegion(region).
		WithCredentials(ec2rolecreds.NewCredentials(session.New()))

	return asgEbs
}

func (asgEbs *AsgEbs) findVolume(tagKey string, tagValue string) (*string, error) {
	svc := ec2.New(session.New(asgEbs.AwsConfig))

	params := &ec2.DescribeVolumesInput{
		Filters: []*ec2.Filter{
			{
				Name: aws.String("tag:" + tagKey),
				Values: []*string{
					aws.String(tagValue),
				},
			},
			{
				Name: aws.String("status"),
				Values: []*string{
					aws.String("available"),
				},
			},
			{
				Name: aws.String("availability-zone"),
				Values: []*string{
					aws.String(asgEbs.AvailabilityZone),
				},
			},
		},
	}

	describeVolumesOutput, err := svc.DescribeVolumes(params)
	if err != nil {
		return nil, err
	}
	if len(describeVolumesOutput.Volumes) == 0 {
		return nil, nil
	}
	return describeVolumesOutput.Volumes[0].VolumeId, nil
}

func (asgEbs *AsgEbs) createVolume(createSize int64, createName string, createVolumeType string, createTags map[string]string) (*string, error) {
	svc := ec2.New(session.New(asgEbs.AwsConfig))

	createVolumeInput := &ec2.CreateVolumeInput{
		AvailabilityZone: &asgEbs.AvailabilityZone,
		Size:             aws.Int64(createSize),
		VolumeType:       aws.String(createVolumeType),
	}
	vol, err := svc.CreateVolume(createVolumeInput)
	if err != nil {
		return nil, err
	}
	tags := []*ec2.Tag{
		{
			Key:   aws.String("Name"),
			Value: aws.String(createName),
		},
	}
	for k, v := range createTags {
		tags = append(tags,
			&ec2.Tag{
				Key:   aws.String(k),
				Value: aws.String(v),
			},
		)
	}

	createTagsInput := &ec2.CreateTagsInput{
		Resources: []*string{vol.VolumeId},
		Tags:      tags,
	}
	_, err = svc.CreateTags(createTagsInput)
	if err != nil {
		return vol.VolumeId, err
	}

	describeVolumeInput := &ec2.DescribeVolumesInput{
		VolumeIds: []*string{vol.VolumeId},
	}
	err = svc.WaitUntilVolumeAvailable(describeVolumeInput)
	if err != nil {
		return vol.VolumeId, err
	}
	return vol.VolumeId, nil
}

func (asgEbs *AsgEbs) attachVolume(volumeId string, attachAs string) error {
	svc := ec2.New(session.New(asgEbs.AwsConfig))

	attachVolumeInput := &ec2.AttachVolumeInput{
		VolumeId:   aws.String(volumeId),
		Device:     aws.String(attachAs),
		InstanceId: aws.String(asgEbs.InstanceId),
	}
	_, err := svc.AttachVolume(attachVolumeInput)
	if err != nil {
		return err
	}

	describeVolumeInput := &ec2.DescribeVolumesInput{
		VolumeIds: []*string{aws.String(volumeId)},
	}
	err = svc.WaitUntilVolumeInUse(describeVolumeInput)
	if err != nil {
		return err
	}

	return nil
}

func (asgEbs *AsgEbs) makeFileSystem(attachAs string) error {
	cmd := exec.Command("/usr/sbin/mkfs.ext4", attachAs)
	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

type CreateTagsValue map[string]string

func (v CreateTagsValue) Set(str string) error {
	parts := strings.SplitN(str, "=", 2)
	if len(parts) != 2 {
		return fmt.Errorf("expected KEY=VALUE got '%s'", str)
	}
	key := parts[0]
	value := parts[1]
	v[key] = value
	return nil
}

func (v CreateTagsValue) String() string {
	return ""
}

func CreateTags(s kingpin.Settings) (target *map[string]string) {
	newMap := make(map[string]string)
	target = &newMap
	s.SetValue((*CreateTagsValue)(target))
	return
}

func main() {
	var (
		tagKey           = kingpin.Flag("tag-key", "The tag key to search for").Required().PlaceHolder("KEY").String()
		tagValue         = kingpin.Flag("tag-value", "The tag value to search for").Required().PlaceHolder("VALUE").String()
		attachAs         = kingpin.Flag("attach-as", "device name e.g. xvdb").Required().PlaceHolder("DEVICE").String()
		create           = kingpin.Flag("create", "Create volume if no volume is available").Bool()
		createSize       = kingpin.Flag("create-size", "The size of the created volume, in GiBs").PlaceHolder("SIZE").Int64()
		createName       = kingpin.Flag("create-name", "The name of the created volume").PlaceHolder("NAME").String()
		createVolumeType = kingpin.Flag("create-volume-type", "The volume type of the created volume. This can be `gp2` for General Purpose (SSD) volumes or `standard` for Magnetic volumes").PlaceHolder("TYPE").Enum("standard", "gp2")
		createTags       = CreateTags(kingpin.Flag("create-tags", "Tag to use for the new volume, can be specified multiple times").PlaceHolder("KEY=VALUE"))
	)

	kingpin.UsageTemplate(kingpin.CompactUsageTemplate)
	kingpin.CommandLine.Help = "Script to attach an EBS Volume to an EC2 instance and optionally create it"
	kingpin.Parse()

	if *create {
		if *createSize == 0 {
			kingpin.Fatalf("required flag --create-size not provided")
		}
		if *createName == "" {
			kingpin.Fatalf("required flag --create-name not provided")
		}
		if *createVolumeType == "" {
			kingpin.Fatalf("required flag --create-volume-type not provided")
		}
	}

	asgEbs := NewAsgEbs()

	volumeCreated := false
	volume, err := asgEbs.findVolume(*tagKey, *tagValue)
	if err != nil {
		log.Fatal("Failed to find volumes", err)
	}

	if volume == nil {
		if *create {
			log.Print("Creating new volume")
			volume, err = asgEbs.createVolume(*createSize, *createName, *createVolumeType, *createTags)
			if err != nil {
				log.Fatal("Failed to create new volume", err)
			}
			volumeCreated = true
		} else {
			log.Print("No available volume can be found")
			os.Exit(2)
		}
	}

	log.Print("Attaching volume ", *volume)
	err = asgEbs.attachVolume(*volume, *attachAs)
	if err != nil {
		log.Fatal("Failed to attach volume", err)
	}

	if volumeCreated {
		log.Print("Creating filesystem on new volume ", *attachAs)
		err = asgEbs.makeFileSystem(*attachAs)
		if err != nil {
			log.Fatal("Failed to create file system", err)
		}
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	yaml "gopkg.in/yaml.v2"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

func main() {
	var (
		apply, dryrun   bool
		file, awsRegion string
	)

	flag.BoolVar(&apply, "apply", false, "apply to CloudWatch Events")
	flag.BoolVar(&dryrun, "dry-run", false, "dry-run")
	flag.StringVar(&file, "file", "config.yml", "file path to setting yaml")
	flag.StringVar(&file, "f", "config.yml", "file path to setting yaml (shorthand)")
	flag.StringVar(&awsRegion, "region", "", "aws region")
	flag.Parse()

	sess, errS := session.NewSession(
		&aws.Config{
			Region: aws.String(awsRegion),
		},
	)
	if errS != nil {
		fmt.Errorf("Session error %v", errS)
		os.Exit(1)
	}

	cweRulesOutput, errR := cloudwatchevents.New(sess).ListRules(nil)
	if errR != nil {
		fmt.Errorf("API error %v", errR)
		os.Exit(1)
	}

	describedRules := Rules{}
	errY := loadYaml(file, &describedRules)
	if errY != nil {
		fmt.Errorf("File error %v", errY)
		os.Exit(1)
	}

	describedRules.Rules = AssociateRules(cweRulesOutput.Rules, describedRules.Rules)
	for i, rule := range describedRules.Rules {
		t, _ := fetchActualTargetsByRule(cloudwatchevents.New(sess), rule)
		describedRules.Rules[i].Targets = AssociateTargets(t, describedRules.Rules[i].Targets)
	}
	CheckIsNeedUpdateOrDelete(describedRules.Rules)
	displayWhatWillChange(describedRules.Rules)

	if apply && !dryrun {
		errU := updateCloudWatchEvents(cloudwatchevents.New(sess), describedRules.Rules)
		if errU != nil {
			fmt.Errorf("API error %v", errU)
			os.Exit(1)
		}
	}
}

func loadYaml(file string, r *Rules) error {

	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(buf, &r)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Change Errorf -> Printf<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	yaml "gopkg.in/yaml.v2"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

func main() {
	var (
		apply, dryrun   bool
		file, awsRegion string
	)

	flag.BoolVar(&apply, "apply", false, "apply to CloudWatch Events")
	flag.BoolVar(&dryrun, "dry-run", false, "dry-run")
	flag.StringVar(&file, "file", "config.yml", "file path to setting yaml")
	flag.StringVar(&file, "f", "config.yml", "file path to setting yaml (shorthand)")
	flag.StringVar(&awsRegion, "region", "", "aws region")
	flag.Parse()

	sess, errS := session.NewSession(
		&aws.Config{
			Region: aws.String(awsRegion),
		},
	)
	if errS != nil {
		fmt.Printf("Session error %v\n", errS)
		os.Exit(1)
	}

	cweRulesOutput, errR := cloudwatchevents.New(sess).ListRules(nil)
	if errR != nil {
		fmt.Printf("API error %v\n", errR)
		os.Exit(1)
	}

	describedRules := Rules{}
	errY := loadYaml(file, &describedRules)
	if errY != nil {
		fmt.Printf("File error %v\n", errY)
		os.Exit(1)
	}

	describedRules.Rules = AssociateRules(cweRulesOutput.Rules, describedRules.Rules)
	for i, rule := range describedRules.Rules {
		t, _ := fetchActualTargetsByRule(cloudwatchevents.New(sess), rule)
		describedRules.Rules[i].Targets = AssociateTargets(t, describedRules.Rules[i].Targets)
	}
	CheckIsNeedUpdateOrDelete(describedRules.Rules)
	displayWhatWillChange(describedRules.Rules)

	if apply && !dryrun {
		errU := updateCloudWatchEvents(cloudwatchevents.New(sess), describedRules.Rules)
		if errU != nil {
			fmt.Printf("API error %v\n", errU)
			os.Exit(1)
		}
	}
}

func loadYaml(file string, r *Rules) error {

	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}

	err = yaml.Unmarshal(buf, &r)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"

	"github.com/FiloSottile/CVE-2016-2107/LuckyMinus20"
)

func main() {
	res, err := LuckyMinus20.Test(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Vulnerable:", res)
	if res {
		os.Exit(1)
	}
}
<commit_msg>Exit with error code 2 for vulnerable to make scripting easier<commit_after>package main

import (
	"log"
	"os"

	"github.com/FiloSottile/CVE-2016-2107/LuckyMinus20"
)

func main() {
	res, err := LuckyMinus20.Test(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Vulnerable:", res)
	if res {
		os.Exit(2)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"os/signal"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/bwmarrin/discordgo"
	"github.com/legolord208/stdutil"
)

type image struct {
	Keyword string
	URL     string
}

const dir = "Dank"

var sounds = make(map[string][][]byte, 0)
var images []*image

var statuses = []string{
	"hidden object games",
	"Oh... Sir!",
	"Minecraft 1.0 ALPHA",
	"with your mother",
	"something",
	"something else",
	"bored",
	"dead"}

type settingsType struct {
	playing   bool
	commander string
}

var settings = make(map[string]*settingsType)
var settingsMutex sync.RWMutex

func main() {
	//stdutil.ShouldTrace = true;
	args := os.Args[1:]

	if len(args) < 1 {
		fmt.Println("No token provided!")
		return
	}
	token := args[0]

	fmt.Println("Loading...")

	err := os.Mkdir(dir, 0755)
	if err != nil && !os.IsExist(err) {
		stdutil.PrintErr("", err)
		return
	}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		name := file.Name()
		if !strings.HasSuffix(name, ".dca") {
			continue
		}

		bytes := make([][]byte, 0)
		err = load(name, &bytes)
		if err != nil {
			continue
		}

		name = strings.ToLower(strings.TrimSuffix(name, ".dca"))
		sounds[name] = bytes
	}

	file, err := os.Open("Dank/images.json")
	if err != nil {
		stdutil.PrintErr("", err)
	} else {
		reader := bufio.NewScanner(file)
		for reader.Scan() {
			parts := strings.SplitN(reader.Text(), ", ", 2)
			if len(parts) != 2 {
				stdutil.PrintErr("Corrupt file or something", nil)
				continue
			}

			images = append(images, &image{
				Keyword: parts[0],
				URL:     parts[1],
			})
		}

		file.Close()

		if err := reader.Err(); err != nil {
			stdutil.PrintErr("Error reading file", err)
			return
		}
	}

	fmt.Println("Starting...")
	session, err := discordgo.New("Bot " + token)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}
	session.AddHandler(messageCreate)
	err = session.Open()

	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	go func() {
		c := time.Tick(time.Minute * 5)

		for _ = range c {
			err := session.UpdateStatus(0, statuses[rand.Intn(len(statuses))])
			if err != nil {
				stdutil.PrintErr("", err)
				return
			}
		}
	}()
	fmt.Println("Started!")

	interrupt := make(chan os.Signal, 2)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	<-interrupt
	fmt.Println("\nExiting")
	session.Close()
}

func load(file string, buffer *[][]byte) error {
	f, err := os.Open(filepath.Join(dir, file))
	defer f.Close()
	if err != nil {
		stdutil.PrintErr("", err)
		return err
	}

	var length int16
	for {
		err := binary.Read(f, binary.LittleEndian, &length)

		if err == io.EOF || err == io.ErrUnexpectedEOF {
			break
		} else if err != nil {
			stdutil.PrintErr("", err)
			return err
		}

		buf := make([]byte, length)
		err = binary.Read(f, binary.LittleEndian, &buf)
		if err != nil {
			stdutil.PrintErr("", err)
			return err
		}

		*buffer = append(*buffer, buf)
	}
	return nil
}

func play(buffer [][]byte, session *discordgo.Session, guild, channel string, s *settingsType) {
	s.playing = true
	defer func() { s.playing = false }()
	vc, err := session.ChannelVoiceJoin(guild, channel, false, true)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	err = vc.Speaking(true)
	if err != nil {
		stdutil.PrintErr("", err)

		err = vc.Disconnect()
		if err != nil {
			stdutil.PrintErr("", err)
		}
		return
	}

	for _, buf := range buffer {
		if !s.playing {
			break
		}
		vc.OpusSend <- buf
	}

	err = vc.Speaking(false)
	if err != nil {
		stdutil.PrintErr("", err)
	}
	err = vc.Disconnect()
	if err != nil {
		stdutil.PrintErr("", err)
	}
}

func messageCreate(session *discordgo.Session, event *discordgo.MessageCreate) {
	if event.Author == nil {
		return
	}
	msg := strings.ToLower(strings.TrimSpace(event.Content))
	author := event.Author

	if msg == "" {
		return
	}

	channel, err := session.State.Channel(event.ChannelID)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	if channel.IsPrivate {
		return
	}

	guild, err := session.State.Guild(channel.GuildID)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	settingsMutex.RLock()
	s := settings[guild.ID]
	settingsMutex.RUnlock()

	if s == nil {
		s = &settingsType{}

		settingsMutex.Lock()
		settings[guild.ID] = s
		settingsMutex.Unlock()
	}

	if msg == "meemz who ur master" {
		msg := ""
		if s.commander == "" {
			msg = "nobody is idiot"
		} else if s.commander == author.ID {
			msg = "u is... idiot"
		} else if s.commander == "-" {
			msg = "im no suppos 2 talk 2 u"
		} else {
			msg = "dat wuld b <@" + s.commander + ">"
		}
		_, err = session.ChannelMessageSend(event.ChannelID, msg)
		if err != nil {
			stdutil.PrintErr("", err)
		}
	}

	if guild.OwnerID == author.ID && strings.HasPrefix(msg, "meemz idfc ") {
		msg = strings.TrimPrefix(msg, "meemz idfc ")
	} else {
		if s.commander != "" && s.commander != author.ID {
			return
		}
	}

	buffer, ok := sounds[msg]
	if ok {
		if !s.playing {
			for _, state := range guild.VoiceStates {
				if state.UserID == event.Author.ID {
					go react(session, event.Message)
					play(buffer, session, guild.ID, state.ChannelID, s)
					return
				}
			}
		}
		return
	}

	for _, image := range images {
		contains, err := regexp.MatchString("(?i)\\b"+regexp.QuoteMeta(image.Keyword)+"\\b", msg)
		if err != nil {
			stdutil.PrintErr("", err)
			return
		}
		if contains {
			go react(session, event.Message)
			_, err = session.ChannelMessageSendEmbed(event.ChannelID,
				&discordgo.MessageEmbed{
					Image: &discordgo.MessageEmbedImage{
						URL: image.URL,
					},
				})
			if err != nil {
				stdutil.PrintErr("", err)
			}
			return
		}
	}

	switch msg {
	case "thx":
		s.playing = false
	case "listen only to me plz":
		s.commander = author.ID
		fmt.Println("In guild '" + guild.Name + "', the user '" + author.Username + "' took control.")
	case "meemz stfu":
		s.commander = "-"
		fmt.Println("In guild '" + guild.Name + "', the user '" + author.Username + "' disabled meemz.")
	case "every1 owns u stopad robot":
		s.commander = ""
		fmt.Println("In guild '" + guild.Name + "', the user '" + author.Username + "' returned the control to everyone.")
	case "plz list da stuff":
		strSounds := ""
		for name := range sounds {
			if strSounds != "" {
				strSounds += ", "
			}
			strSounds += "`" + name + "`"
		}

		strImages := ""
		for _, image := range images {
			if strImages != "" {
				strImages += ", "
			}
			strImages += "`" + image.Keyword + "`"
		}

		_, err := session.ChannelMessageSendEmbed(event.ChannelID, &discordgo.MessageEmbed{
			Fields: []*discordgo.MessageEmbedField{
				&discordgo.MessageEmbedField{
					Name:  "DA SOUNDZ",
					Value: strSounds,
				},
				&discordgo.MessageEmbedField{
					Name:   "DA IMAGEZ",
					Value:  strImages,
					Inline: true,
				},
			},
		})
		if err != nil {
			stdutil.PrintErr("", err)
			return
		}
	}
}

func react(session *discordgo.Session, event *discordgo.Message) {
	err := session.MessageReactionAdd(event.ChannelID, event.ID, "👌")
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}
	err = session.MessageReactionAdd(event.ChannelID, event.ID, "😂")
	if err != nil {
		stdutil.PrintErr("", err)
	}
}
<commit_msg>Don't match emojis<commit_after>package main

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"os"
	"os/signal"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/bwmarrin/discordgo"
	"github.com/legolord208/stdutil"
)

type image struct {
	Keyword string
	URL     string
}

const dir = "Dank"

var sounds = make(map[string][][]byte, 0)
var images []*image

var statuses = []string{
	"hidden object games",
	"Oh... Sir!",
	"Minecraft 1.0 ALPHA",
	"with your mother",
	"something",
	"something else",
	"bored",
	"dead"}

type settingsType struct {
	playing   bool
	commander string
}

var settings = make(map[string]*settingsType)
var settingsMutex sync.RWMutex

func main() {
	//stdutil.ShouldTrace = true;
	args := os.Args[1:]

	if len(args) < 1 {
		fmt.Println("No token provided!")
		return
	}
	token := args[0]

	fmt.Println("Loading...")

	err := os.Mkdir(dir, 0755)
	if err != nil && !os.IsExist(err) {
		stdutil.PrintErr("", err)
		return
	}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		name := file.Name()
		if !strings.HasSuffix(name, ".dca") {
			continue
		}

		bytes := make([][]byte, 0)
		err = load(name, &bytes)
		if err != nil {
			continue
		}

		name = strings.ToLower(strings.TrimSuffix(name, ".dca"))
		sounds[name] = bytes
	}

	file, err := os.Open("Dank/images.txt")
	if err != nil {
		stdutil.PrintErr("", err)
	} else {
		reader := bufio.NewScanner(file)
		for reader.Scan() {
			parts := strings.SplitN(reader.Text(), ", ", 2)
			if len(parts) != 2 {
				stdutil.PrintErr("Corrupt file or something", nil)
				continue
			}

			images = append(images, &image{
				Keyword: parts[0],
				URL:     parts[1],
			})
		}

		file.Close()

		if err := reader.Err(); err != nil {
			stdutil.PrintErr("Error reading file", err)
			return
		}
	}

	fmt.Println("Starting...")
	session, err := discordgo.New("Bot " + token)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}
	session.AddHandler(messageCreate)
	err = session.Open()

	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	go func() {
		c := time.Tick(time.Minute * 5)

		for _ = range c {
			err := session.UpdateStatus(0, statuses[rand.Intn(len(statuses))])
			if err != nil {
				stdutil.PrintErr("", err)
				return
			}
		}
	}()
	fmt.Println("Started!")

	interrupt := make(chan os.Signal, 2)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	<-interrupt
	fmt.Println("\nExiting")
	session.Close()
}

func load(file string, buffer *[][]byte) error {
	f, err := os.Open(filepath.Join(dir, file))
	defer f.Close()
	if err != nil {
		stdutil.PrintErr("", err)
		return err
	}

	var length int16
	for {
		err := binary.Read(f, binary.LittleEndian, &length)

		if err == io.EOF || err == io.ErrUnexpectedEOF {
			break
		} else if err != nil {
			stdutil.PrintErr("", err)
			return err
		}

		buf := make([]byte, length)
		err = binary.Read(f, binary.LittleEndian, &buf)
		if err != nil {
			stdutil.PrintErr("", err)
			return err
		}

		*buffer = append(*buffer, buf)
	}
	return nil
}

func play(buffer [][]byte, session *discordgo.Session, guild, channel string, s *settingsType) {
	s.playing = true
	defer func() { s.playing = false }()
	vc, err := session.ChannelVoiceJoin(guild, channel, false, true)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	err = vc.Speaking(true)
	if err != nil {
		stdutil.PrintErr("", err)

		err = vc.Disconnect()
		if err != nil {
			stdutil.PrintErr("", err)
		}
		return
	}

	for _, buf := range buffer {
		if !s.playing {
			break
		}
		vc.OpusSend <- buf
	}

	err = vc.Speaking(false)
	if err != nil {
		stdutil.PrintErr("", err)
	}
	err = vc.Disconnect()
	if err != nil {
		stdutil.PrintErr("", err)
	}
}

func messageCreate(session *discordgo.Session, event *discordgo.MessageCreate) {
	if event.Author == nil {
		return
	}
	msg := strings.ToLower(strings.TrimSpace(event.Content))
	author := event.Author

	if msg == "" {
		return
	}

	channel, err := session.State.Channel(event.ChannelID)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	if channel.IsPrivate {
		return
	}

	guild, err := session.State.Guild(channel.GuildID)
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}

	settingsMutex.RLock()
	s := settings[guild.ID]
	settingsMutex.RUnlock()

	if s == nil {
		s = &settingsType{}

		settingsMutex.Lock()
		settings[guild.ID] = s
		settingsMutex.Unlock()
	}

	if msg == "meemz who ur master" {
		msg := ""
		if s.commander == "" {
			msg = "nobody is idiot"
		} else if s.commander == author.ID {
			msg = "u is... idiot"
		} else if s.commander == "-" {
			msg = "im no suppos 2 talk 2 u"
		} else {
			msg = "dat wuld b <@" + s.commander + ">"
		}
		_, err = session.ChannelMessageSend(event.ChannelID, msg)
		if err != nil {
			stdutil.PrintErr("", err)
		}
	}

	if guild.OwnerID == author.ID && strings.HasPrefix(msg, "meemz idfc ") {
		msg = strings.TrimPrefix(msg, "meemz idfc ")
	} else {
		if s.commander != "" && s.commander != author.ID {
			return
		}
	}

	buffer, ok := sounds[msg]
	if ok {
		if !s.playing {
			for _, state := range guild.VoiceStates {
				if state.UserID == event.Author.ID {
					go react(session, event.Message)
					play(buffer, session, guild.ID, state.ChannelID, s)
					return
				}
			}
		}
		return
	}

	for _, image := range images {
		contains, err := regexp.MatchString(`(^|[^:])\b`+regexp.QuoteMeta(image.Keyword)+`\b($|[^:])`, msg)
		if err != nil {
			stdutil.PrintErr("", err)
			return
		}
		if contains {
			go react(session, event.Message)
			_, err = session.ChannelMessageSendEmbed(event.ChannelID,
				&discordgo.MessageEmbed{
					Image: &discordgo.MessageEmbedImage{
						URL: image.URL,
					},
				})
			if err != nil {
				stdutil.PrintErr("", err)
			}
			return
		}
	}

	switch msg {
	case "thx":
		s.playing = false
	case "listen only to me plz":
		s.commander = author.ID
		fmt.Println("In guild '" + guild.Name + "', the user '" + author.Username + "' took control.")
	case "meemz stfu":
		s.commander = "-"
		fmt.Println("In guild '" + guild.Name + "', the user '" + author.Username + "' disabled meemz.")
	case "every1 owns u stopad robot":
		s.commander = ""
		fmt.Println("In guild '" + guild.Name + "', the user '" + author.Username + "' returned the control to everyone.")
	case "plz list da stuff":
		strSounds := ""
		for name := range sounds {
			if strSounds != "" {
				strSounds += ", "
			}
			strSounds += "`" + name + "`"
		}

		strImages := ""
		for _, image := range images {
			if strImages != "" {
				strImages += ", "
			}
			strImages += "`" + image.Keyword + "`"
		}

		_, err := session.ChannelMessageSendEmbed(event.ChannelID, &discordgo.MessageEmbed{
			Fields: []*discordgo.MessageEmbedField{
				&discordgo.MessageEmbedField{
					Name:  "DA SOUNDZ",
					Value: strSounds,
				},
				&discordgo.MessageEmbedField{
					Name:   "DA IMAGEZ",
					Value:  strImages,
					Inline: true,
				},
			},
		})
		if err != nil {
			stdutil.PrintErr("", err)
			return
		}
	}
}

func react(session *discordgo.Session, event *discordgo.Message) {
	err := session.MessageReactionAdd(event.ChannelID, event.ID, "👌")
	if err != nil {
		stdutil.PrintErr("", err)
		return
	}
	err = session.MessageReactionAdd(event.ChannelID, event.ID, "😂")
	if err != nil {
		stdutil.PrintErr("", err)
	}
}
<|endoftext|>


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

package main

import (
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"runtime/pprof"
	"strings"
	"syscall"
	"time"

	"github.com/braintree/manners"
	"github.com/codegangsta/cli"
)

func handleSignals(server *manners.GracefulServer) {
	sigChan := make(chan os.Signal, 3)
	go func() {
		for sig := range sigChan {
			if sig == os.Interrupt || sig == os.Kill {
				server.Close()
			}
			if sig == syscall.SIGUSR1 {
				var buf []byte
				var written int
				currLen := 1024
				for written == len(buf) {
					buf = make([]byte, currLen)
					written = runtime.Stack(buf, true)
					currLen *= 2
				}
				log.Print(string(buf[:written]))
			}
			if sig == syscall.SIGUSR2 {
				go func() {
					cpufile, _ := os.OpenFile("./planb_cpu.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
					memfile, _ := os.OpenFile("./planb_mem.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
					log.Println("enabling profile...")
					pprof.WriteHeapProfile(memfile)
					memfile.Close()
					pprof.StartCPUProfile(cpufile)
					time.Sleep(60 * time.Second)
					pprof.StopCPUProfile()
					cpufile.Close()
					log.Println("profiling done")
				}()
			}
		}
	}()
	signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2)
}

func runServer(c *cli.Context) {
	listener, err := net.Listen("tcp", c.String("listen"))
	if err != nil {
		log.Fatal(err)
	}
	router := Router{
		ReadRedisHost:   c.String("read-redis-host"),
		ReadRedisPort:   c.Int("read-redis-port"),
		WriteRedisHost:  c.String("write-redis-host"),
		WriteRedisPort:  c.Int("write-redis-port"),
		LogPath:         c.String("access-log"),
		RequestTimeout:  time.Duration(c.Int("request-timeout")) * time.Second,
		DialTimeout:     time.Duration(c.Int("dial-timeout")) * time.Second,
		DeadBackendTTL:  c.Int("dead-backend-time"),
		FlushInterval:   time.Duration(c.Int("flush-interval")) * time.Millisecond,
		RequestIDHeader: c.String("request-id-header"),
	}
	err = router.Init()
	if err != nil {
		log.Fatal(err)
	}
	s := manners.NewWithServer(&http.Server{Handler: &router})
	handleSignals(s)
	log.Printf("Listening on %v...\n", listener.Addr())
	err = s.Serve(listener)
	router.Stop()
	if err != nil {
		log.Fatal(err)
	}
}

func fixUsage(s string) string {
	parts := strings.Split(s, " ")
	currLen := 0
	lastPart := 0
	var lines []string
	for i := range parts {
		if currLen+len(parts[i])+1 > 55 {
			lines = append(lines, strings.Join(parts[lastPart:i], " "))
			currLen = 0
			lastPart = i
		}
		currLen += len(parts[i]) + 1
	}
	lines = append(lines, strings.Join(parts[lastPart:], " "))
	return strings.Join(lines, "\n\t")
}

func main() {
	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "listen, l",
			Value: "0.0.0.0:8989",
			Usage: "Address to listen",
		},
		cli.StringFlag{
			Name:  "read-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "read-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "write-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "write-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "access-log",
			Value: "./access.log",
			Usage: fixUsage("File path where access log will be written. If value equals `syslog` log will be sent to local syslog."),
		},
		cli.IntFlag{
			Name:  "request-timeout",
			Value: 30,
			Usage: "Total backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dial-timeout",
			Value: 10,
			Usage: "Dial backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dead-backend-time",
			Value: 30,
			Usage: fixUsage("Time in seconds a backend will remain disabled after a network failure."),
		},
		cli.IntFlag{
			Name:  "flush-interval",
			Value: 10,
			Usage: fixUsage("Time in milliseconds to flush the proxied request."),
		},
		cli.StringFlag{
			Name: "request-id-header",
		},
	}
	app.Version = "0.1.4"
	app.Name = "planb"
	app.Usage = "http and websockets reverse proxy"
	app.Action = runServer
	app.Author = "tsuru team"
	app.Email = "https://github.com/tsuru/planb"
	app.Run(os.Args)
}
<commit_msg>main: bump to 0.1.5<commit_after>// Copyright 2015 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"runtime/pprof"
	"strings"
	"syscall"
	"time"

	"github.com/braintree/manners"
	"github.com/codegangsta/cli"
)

func handleSignals(server *manners.GracefulServer) {
	sigChan := make(chan os.Signal, 3)
	go func() {
		for sig := range sigChan {
			if sig == os.Interrupt || sig == os.Kill {
				server.Close()
			}
			if sig == syscall.SIGUSR1 {
				var buf []byte
				var written int
				currLen := 1024
				for written == len(buf) {
					buf = make([]byte, currLen)
					written = runtime.Stack(buf, true)
					currLen *= 2
				}
				log.Print(string(buf[:written]))
			}
			if sig == syscall.SIGUSR2 {
				go func() {
					cpufile, _ := os.OpenFile("./planb_cpu.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
					memfile, _ := os.OpenFile("./planb_mem.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
					log.Println("enabling profile...")
					pprof.WriteHeapProfile(memfile)
					memfile.Close()
					pprof.StartCPUProfile(cpufile)
					time.Sleep(60 * time.Second)
					pprof.StopCPUProfile()
					cpufile.Close()
					log.Println("profiling done")
				}()
			}
		}
	}()
	signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2)
}

func runServer(c *cli.Context) {
	listener, err := net.Listen("tcp", c.String("listen"))
	if err != nil {
		log.Fatal(err)
	}
	router := Router{
		ReadRedisHost:   c.String("read-redis-host"),
		ReadRedisPort:   c.Int("read-redis-port"),
		WriteRedisHost:  c.String("write-redis-host"),
		WriteRedisPort:  c.Int("write-redis-port"),
		LogPath:         c.String("access-log"),
		RequestTimeout:  time.Duration(c.Int("request-timeout")) * time.Second,
		DialTimeout:     time.Duration(c.Int("dial-timeout")) * time.Second,
		DeadBackendTTL:  c.Int("dead-backend-time"),
		FlushInterval:   time.Duration(c.Int("flush-interval")) * time.Millisecond,
		RequestIDHeader: c.String("request-id-header"),
	}
	err = router.Init()
	if err != nil {
		log.Fatal(err)
	}
	s := manners.NewWithServer(&http.Server{Handler: &router})
	handleSignals(s)
	log.Printf("Listening on %v...\n", listener.Addr())
	err = s.Serve(listener)
	router.Stop()
	if err != nil {
		log.Fatal(err)
	}
}

func fixUsage(s string) string {
	parts := strings.Split(s, " ")
	currLen := 0
	lastPart := 0
	var lines []string
	for i := range parts {
		if currLen+len(parts[i])+1 > 55 {
			lines = append(lines, strings.Join(parts[lastPart:i], " "))
			currLen = 0
			lastPart = i
		}
		currLen += len(parts[i]) + 1
	}
	lines = append(lines, strings.Join(parts[lastPart:], " "))
	return strings.Join(lines, "\n\t")
}

func main() {
	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "listen, l",
			Value: "0.0.0.0:8989",
			Usage: "Address to listen",
		},
		cli.StringFlag{
			Name:  "read-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "read-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "write-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "write-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "access-log",
			Value: "./access.log",
			Usage: fixUsage("File path where access log will be written. If value equals `syslog` log will be sent to local syslog."),
		},
		cli.IntFlag{
			Name:  "request-timeout",
			Value: 30,
			Usage: "Total backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dial-timeout",
			Value: 10,
			Usage: "Dial backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dead-backend-time",
			Value: 30,
			Usage: fixUsage("Time in seconds a backend will remain disabled after a network failure."),
		},
		cli.IntFlag{
			Name:  "flush-interval",
			Value: 10,
			Usage: fixUsage("Time in milliseconds to flush the proxied request."),
		},
		cli.StringFlag{
			Name: "request-id-header",
		},
	}
	app.Version = "0.1.5"
	app.Name = "planb"
	app.Usage = "http and websockets reverse proxy"
	app.Action = runServer
	app.Author = "tsuru team"
	app.Email = "https://github.com/tsuru/planb"
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"log"
	"os"
	"os/user"
	"strconv"
	"time"

	"github.com/nishanths/go-hgconfig"
	"github.com/tcnksm/go-gitconfig"
)

const (
	nameEnv       = "LICENSE_FULL_NAME"
	versionString = "1.0.0"
	usageString   = "license [FLAGS] [LICENSE NAME]"
	helpString    = `usage: ` + usageString + `

Flags:
       -auth     GitHub credentials in format "username:token" for updating licenses (optional)
       -help     print help information
       -list     list available licenses
   -n, -name     full name on license (default %q)
   -o, -output   output filename (prints to stdout if not specified)
       -update   update all licenses to latest from GitHub
       -version  print version
   -y, -year     year on license (default %q)

Examples:
  license mit
  license -name Alice isc
  license -o LICENSE.txt mpl-2.0`
)

var (
	logger    = log.New(os.Stdout, "", 0)
	errLogger = log.New(os.Stderr, "", 0)
	flags     = struct {
		License string // Type of license.
		Name    string // Name on license.
		Year    string // Year on license.
		Output  string // Output file.
		Auth    string
		Version bool
		Help    bool
		List    bool
		Update  bool
	}{}
)

func setupFlags() {
	flag.StringVar(&flags.Name, "name", name(), "name on license")
	flag.StringVar(&flags.Name, "n", name(), "name on license")

	flag.StringVar(&flags.Year, "year", year(), "year on license")
	flag.StringVar(&flags.Year, "y", year(), "year on license")

	flag.StringVar(&flags.Output, "output", "", "path to output file")
	flag.StringVar(&flags.Output, "o", "", "path to output file")

	flag.StringVar(&flags.Auth, "auth", "", "GitHub authentication")
	flag.BoolVar(&flags.Version, "version", false, "print version")
	flag.BoolVar(&flags.Help, "help", false, "print help")
	flag.BoolVar(&flags.List, "list", false, "print available licenses")
	flag.BoolVar(&flags.Update, "update", false, "get latest licenses")

}

var ErrMissingArg = errors.New("error: require license name")

func checkFlags() error {
	if flags.License == "" && !(flags.Update || flags.Version || flags.Help || flags.List) {
		return ErrMissingArg
	}
	return nil
}

func main() {
	setupFlags()
	flag.Usage = usage
	flag.Parse()

	flags.License = flag.Arg(0)

	if err := checkFlags(); err != nil {
		errLogger.Println(err)
		usage()
		os.Exit(1)
	}

	mainImpl()
}

func mainImpl() {
	// If any of the -version, -help, -list, or -update flags
	// is specified, the rest of the arguments is ignored.

	switch {
	case flags.Version:
		version()
	case flags.Help:
		help()
	case flags.List:
		list()
	case flags.Update:
		update()
	}

	generate()
	os.Exit(2)
}

func version() {
	errLogger.Printf("v%s\n", versionString)
	os.Exit(0)
}

func help() {
	errLogger.Printf(helpString+"\n", name(), year())
	os.Exit(0)
}

func usage() {
	errLogger.Println("usage: " + usageString)
	errLogger.Println("see 'license -help' for more details")
}

func name() string {
	n := os.Getenv(nameEnv)
	if n != "" {
		return n
	}
	n, err := gitconfig.Username()
	if err == nil {
		return n
	}
	n, err = gitconfig.Global("user.name")
	if err != nil {
		return n
	}
	n, err = hgconfig.Username()
	if err != nil {
		return n
	}
	usr, err := user.Current()
	if err != nil {
		return usr.Name
	}
	return ""
}

func year() string {
	return strconv.Itoa(time.Now().Year())
}
<commit_msg>Fix err checks in name()<commit_after>package main

import (
	"errors"
	"flag"
	"log"
	"os"
	"os/user"
	"strconv"
	"time"

	"github.com/nishanths/go-hgconfig"
	"github.com/tcnksm/go-gitconfig"
)

const (
	nameEnv       = "LICENSE_FULL_NAME"
	versionString = "1.0.0"
	usageString   = "license [FLAGS] [LICENSE NAME]"
	helpString    = `usage: ` + usageString + `

Flags:
       -auth     GitHub credentials in format "username:token" for updating licenses (optional)
       -help     print help information
       -list     list available licenses
   -n, -name     full name on license (default %q)
   -o, -output   output filename (prints to stdout if not specified)
       -update   update all licenses to latest from GitHub
       -version  print version
   -y, -year     year on license (default %q)

Examples:
  license mit
  license -name Alice isc
  license -o LICENSE.txt mpl-2.0`
)

var (
	logger    = log.New(os.Stdout, "", 0)
	errLogger = log.New(os.Stderr, "", 0)
	flags     = struct {
		License string // Type of license.
		Name    string // Name on license.
		Year    string // Year on license.
		Output  string // Output file.
		Auth    string
		Version bool
		Help    bool
		List    bool
		Update  bool
	}{}
)

func setupFlags() {
	flag.StringVar(&flags.Name, "name", name(), "name on license")
	flag.StringVar(&flags.Name, "n", name(), "name on license")

	flag.StringVar(&flags.Year, "year", year(), "year on license")
	flag.StringVar(&flags.Year, "y", year(), "year on license")

	flag.StringVar(&flags.Output, "output", "", "path to output file")
	flag.StringVar(&flags.Output, "o", "", "path to output file")

	flag.StringVar(&flags.Auth, "auth", "", "GitHub authentication")
	flag.BoolVar(&flags.Version, "version", false, "print version")
	flag.BoolVar(&flags.Help, "help", false, "print help")
	flag.BoolVar(&flags.List, "list", false, "print available licenses")
	flag.BoolVar(&flags.Update, "update", false, "get latest licenses")

}

var ErrMissingArg = errors.New("error: require license name")

func checkFlags() error {
	if flags.License == "" && !(flags.Update || flags.Version || flags.Help || flags.List) {
		return ErrMissingArg
	}
	return nil
}

func main() {
	setupFlags()
	flag.Usage = usage
	flag.Parse()

	flags.License = flag.Arg(0)

	if err := checkFlags(); err != nil {
		errLogger.Println(err)
		usage()
		os.Exit(1)
	}

	mainImpl()
}

func mainImpl() {
	// If any of the -version, -help, -list, or -update flags
	// is specified, the rest of the arguments is ignored.

	switch {
	case flags.Version:
		version()
	case flags.Help:
		help()
	case flags.List:
		list()
	case flags.Update:
		update()
	}

	generate()
	os.Exit(2)
}

func version() {
	errLogger.Printf("v%s\n", versionString)
	os.Exit(0)
}

func help() {
	errLogger.Printf(helpString+"\n", name(), year())
	os.Exit(0)
}

func usage() {
	errLogger.Println("usage: " + usageString)
	errLogger.Println("see 'license -help' for more details")
}

func name() string {
	n := os.Getenv(nameEnv)
	if n != "" {
		return n
	}
	n, err := gitconfig.Username()
	if err == nil {
		return n
	}
	n, err = gitconfig.Global("user.name")
	if err == nil {
		return n
	}
	n, err = hgconfig.Username()
	if err == nil {
		return n
	}
	usr, err := user.Current()
	if err == nil {
		return usr.Name
	}
	return ""
}

func year() string {
	return strconv.Itoa(time.Now().Year())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"sort"
)

const (
	VERSION      = "1.2.0"
	NAME         = "gotags"
	URL          = "https://github.com/jstemmer/gotags"
	AUTHOR_NAME  = "Joel Stemmer"
	AUTHOR_EMAIL = "stemmertech@gmail.com"
)

var (
	printVersion bool
	inputFile    string
	sortOutput   bool
	silent       bool
	printTree    bool // for debugging
)

// Initialize flags.
func init() {
	flag.BoolVar(&printVersion, "v", false, "print version")
	flag.StringVar(&inputFile, "L", "", "source file names are read from the specified file.")
	flag.BoolVar(&sortOutput, "sort", true, "sort tags")
	flag.BoolVar(&silent, "silent", false, "do not produce any output on error")
	flag.BoolVar(&printTree, "tree", false, "print syntax tree (debugging)")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "gotags version %s\n\n", VERSION)
		fmt.Fprintf(os.Stderr, "Usage: %s [options] file(s)\n\n", os.Args[0])
		flag.PrintDefaults()
	}
}

func getFileNames() ([]string, error) {
	var names []string

	names = append(names, flag.Args()...)

	if len(inputFile) == 0 {
		return names, nil
	}

	var scanner *bufio.Scanner
	if inputFile != "-" {
		in, err := os.Open(inputFile)
		if err != nil {
			return nil, err
		}

		defer in.Close()
		scanner = bufio.NewScanner(in)
	} else {
		scanner = bufio.NewScanner(os.Stdin)
	}

	for scanner.Scan() {
		names = append(names, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return names, nil
}

func main() {
	flag.Parse()

	if printVersion {
		fmt.Printf("gotags version %s\n", VERSION)
		return
	}

	files, err := getFileNames()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot get specified files\n\n")
		flag.Usage()
		os.Exit(1)
	}

	if len(files) == 0 && len(inputFile) == 0 {
		fmt.Fprintf(os.Stderr, "no file specified\n\n")
		flag.Usage()
		os.Exit(1)
	}

	if printTree {
		PrintTree(flag.Arg(0))
		return
	}

	tags := []Tag{}
	for _, file := range files {
		ts, err := Parse(file)
		if err != nil {
			if !silent {
				fmt.Fprintf(os.Stderr, "parse error: %s\n\n", err)
			}
			continue
		}
		tags = append(tags, ts...)
	}

	output := createMetaTags()
	for _, tag := range tags {
		output = append(output, tag.String())
	}

	if sortOutput {
		sort.Sort(sort.StringSlice(output))
	}

	for _, s := range output {
		fmt.Println(s)
	}
}

// createMetaTags returns a list of meta tags.
func createMetaTags() []string {
	var sorted int
	if sortOutput {
		sorted = 1
	}
	return []string{
		"!_TAG_FILE_FORMAT\t2\t",
		fmt.Sprintf("!_TAG_FILE_SORTED\t%d\t/0=unsorted, 1=sorted/", sorted),
		fmt.Sprintf("!_TAG_PROGRAM_AUTHOR\t%s\t/%s/", AUTHOR_NAME, AUTHOR_EMAIL),
		fmt.Sprintf("!_TAG_PROGRAM_NAME\t%s\t", NAME),
		fmt.Sprintf("!_TAG_PROGRAM_URL\t%s\t", URL),
		fmt.Sprintf("!_TAG_PROGRAM_VERSION\t%s\t", VERSION),
	}
}
<commit_msg>Listing go files recursively with -R flag<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

const (
	VERSION      = "1.2.0"
	NAME         = "gotags"
	URL          = "https://github.com/jstemmer/gotags"
	AUTHOR_NAME  = "Joel Stemmer"
	AUTHOR_EMAIL = "stemmertech@gmail.com"
)

var (
	printVersion bool
	inputFile    string
	recurse      bool
	sortOutput   bool
	silent       bool
	printTree    bool // for debugging
)

// Initialize flags.
func init() {
	flag.BoolVar(&printVersion, "v", false, "print version")
	flag.StringVar(&inputFile, "L", "", "source file names are read from the specified file.")
	flag.BoolVar(&recurse, "R", false, "recurse into directories in the file list")
	flag.BoolVar(&sortOutput, "sort", true, "sort tags")
	flag.BoolVar(&silent, "silent", false, "do not produce any output on error")
	flag.BoolVar(&printTree, "tree", false, "print syntax tree (debugging)")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "gotags version %s\n\n", VERSION)
		fmt.Fprintf(os.Stderr, "Usage: %s [options] file(s)\n\n", os.Args[0])
		flag.PrintDefaults()
	}
}

func walkDir(names []string, dir string) ([]string, error) {
	e := filepath.Walk(dir, func(path string, _ os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if strings.HasSuffix(path, ".go") {
			names = append(names, path)
		}
		return nil
	})

	return names, e
}

func recurseNames(names []string) ([]string, error) {
	var ret []string
	for _, name := range names {
		info, e := os.Stat(name)
		if e != nil || info == nil || !info.IsDir() {
			ret = append(ret, name) // defer the error handling to the scanner
		} else {
			ret, e = walkDir(ret, name)
			if e != nil {
				return names, e
			}
		}
	}
	return ret, nil
}

func readNames(names []string) ([]string, error) {
	if len(inputFile) == 0 {
		return names, nil
	}

	var scanner *bufio.Scanner
	if inputFile != "-" {
		in, err := os.Open(inputFile)
		if err != nil {
			return nil, err
		}

		defer in.Close()
		scanner = bufio.NewScanner(in)
	} else {
		scanner = bufio.NewScanner(os.Stdin)
	}

	for scanner.Scan() {
		names = append(names, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return names, nil
}

func getFileNames() ([]string, error) {
	var names []string

	names = append(names, flag.Args()...)
	names, err := readNames(names)
	if err != nil {
		return nil, err
	}

	if recurse {
		names, err = recurseNames(names)
		if err != nil {
			return nil, err
		}
	}

	return names, nil
}

func main() {
	flag.Parse()

	if printVersion {
		fmt.Printf("gotags version %s\n", VERSION)
		return
	}

	files, err := getFileNames()
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot get specified files\n\n")
		flag.Usage()
		os.Exit(1)
	}

	if len(files) == 0 && len(inputFile) == 0 {
		fmt.Fprintf(os.Stderr, "no file specified\n\n")
		flag.Usage()
		os.Exit(1)
	}

	if printTree {
		PrintTree(flag.Arg(0))
		return
	}

	tags := []Tag{}
	for _, file := range files {
		ts, err := Parse(file)
		if err != nil {
			if !silent {
				fmt.Fprintf(os.Stderr, "parse error: %s\n\n", err)
			}
			continue
		}
		tags = append(tags, ts...)
	}

	output := createMetaTags()
	for _, tag := range tags {
		output = append(output, tag.String())
	}

	if sortOutput {
		sort.Sort(sort.StringSlice(output))
	}

	for _, s := range output {
		fmt.Println(s)
	}
}

// createMetaTags returns a list of meta tags.
func createMetaTags() []string {
	var sorted int
	if sortOutput {
		sorted = 1
	}
	return []string{
		"!_TAG_FILE_FORMAT\t2\t",
		fmt.Sprintf("!_TAG_FILE_SORTED\t%d\t/0=unsorted, 1=sorted/", sorted),
		fmt.Sprintf("!_TAG_PROGRAM_AUTHOR\t%s\t/%s/", AUTHOR_NAME, AUTHOR_EMAIL),
		fmt.Sprintf("!_TAG_PROGRAM_NAME\t%s\t", NAME),
		fmt.Sprintf("!_TAG_PROGRAM_URL\t%s\t", URL),
		fmt.Sprintf("!_TAG_PROGRAM_VERSION\t%s\t", VERSION),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"encoding/csv"
	"encoding/json"
	"flag"
	"fmt"
	"hash/crc64"
	"html/template"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/cloudflare/cloudflare-go"
	"github.com/gortc/ice"
	"github.com/gortc/sdp"
	"github.com/gortc/stun"
	"github.com/mssola/user_agent"
)

var (
	portHTTP = flag.Int("port", 3000, "http server port")
	hostHTTP = flag.String("host", "localhost", "http server host")
	portSTUN = flag.Int("port-stun", stun.DefaultPort, "UDP port")
)

var (
	bindingRequest = stun.MessageType{
		Method: stun.MethodBinding,
		Class:  stun.ClassRequest,
	}
	bindingSuccessResponse = stun.MessageType{
		Method: stun.MethodBinding,
		Class:  stun.ClassSuccessResponse,
	}
)

func processUDPPacket(addr net.Addr, b []byte, req, res *stun.Message) error {
	if !stun.IsMessage(b) {
		log.Println("packet from", addr, "is not STUN message")
		return nil
	}
	req.Raw = b
	if err := req.Decode(); err != nil {
		return err
	}
	if req.Type != bindingRequest {
		log.Println("stun: skipping", req.Type, "from", addr)
		return nil
	}
	log.Println("stun: got", req.Type)
	res.TransactionID = req.TransactionID
	res.Type = bindingSuccessResponse
	var (
		ip   net.IP
		port int
	)
	switch a := addr.(type) {
	case *net.UDPAddr:
		ip = a.IP
		port = a.Port
	default:
		panic(fmt.Sprintf("unknown addr: %v", addr))
	}
	stun.XORMappedAddress{
		IP:   ip,
		Port: port,
	}.AddTo(res)
	stun.NewSoftware("gortc.io/x/sdp example").AddTo(res)
	res.WriteHeader()
	messages.add(fmt.Sprintf("%s:%d", ip, port), req)
	return nil
}

type iceServerConfiguration struct {
	URLs []string `json:"urls"`
}

type iceConfiguration struct {
	Servers []iceServerConfiguration `json:"iceServers"`
}

func main() {
	flag.Parse()
	cf, err := cloudflare.New(
		os.Getenv("CF_API_KEY"),
		os.Getenv("CF_API_EMAIL"),
	)
	if err != nil {
		log.Fatal(err)
	}
	t, err := template.ParseFiles("static/index.html")
	if err != nil {
		log.Fatal(err)
	}
	log.SetFlags(log.Lshortfile)
	fs := http.FileServer(http.Dir("static"))
	var (
		s     *stats
		sLock sync.RWMutex
	)
	go func() {
		sLock.Lock()
		log.Println("gettings stats")
		s, err = getStats(false)
		if err != nil {
			log.Println("failed to get stats:", err)
		} else {
			log.Println("got stats")
		}
		sLock.Unlock()
	}()
	update := func() error {
		log.Println("updating stats")
		newStats, err := getStats(true)
		if err != nil {
			log.Println("failed to fetch stats:", err)
			return err
		}
		sLock.Lock()
		s = newStats
		sLock.Unlock()
		return nil
	}
	go func() {
		ticker := time.NewTicker(time.Second * 90)
		for range ticker.C {
			_ = update()
		}
	}()
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		q := r.URL.Query()
		// path: /foo
		//       /foo/...
		// package: foo
		pkg := strings.TrimPrefix(r.URL.Path, "/")
		if i := strings.Index(pkg, "/"); i != -1 {
			pkg = pkg[:i]
		}

		if q.Get("go-get") == "1" && pkg != "" {
			// Custom domain support.
			// TODO: Check github org.
			body := strings.Replace(`<!DOCTYPE html>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="go-import" content="gortc.io/pkg git https://github.com/gortc/pkg.git">
    <meta name="go-source"
          content="gortc.io/pkg https://github.com/gortc/pkg/ https://github.com/gortc/pkg/tree/master{/dir} https://github.com/gortc/pkg/blob/master{/dir}/{file}#L{line}">
    <meta http-equiv="refresh" content="0; url=https://godoc.org/gortc.io/pkg">

Nothing to see here; move along.
`, "pkg", pkg, -1)
			fmt.Fprintln(w, body)
			return
		}
		if r.URL.Path != "/" {
			fs.ServeHTTP(w, r)
			return
		}
		w.Header().Add("Link", "</go-rtc.svg>; as=image; rel=preload")
		w.Header().Add("Link", "</jetbrains-variant-3.svg>; as=image; rel=preload")
		w.Header().Add("Link", "</css/main.css>; as=style; rel=preload")
		sLock.RLock()
		if err := t.Execute(w, s); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintln(w, err)
		}
		sLock.RUnlock()
	})
	http.HandleFunc("/hook/"+os.Getenv("GITHUB_HOOK_SECRET"), func(writer http.ResponseWriter, request *http.Request) {
		start := time.Now()
		err := update()
		if err != nil {
			writer.WriteHeader(http.StatusInternalServerError)
			fmt.Println(writer, "failed:", err)
			return
		}
		writer.WriteHeader(http.StatusOK)
		fmt.Fprintln(writer, "updated in", time.Since(start))
		go func() {
			log.Println("purging cf cache")
			zoneID, err := cf.ZoneIDByName("gortc.io")
			if err != nil {
				log.Println("failed to get zone id:", err)
				return
			}
			res, err := cf.PurgeCache(zoneID, cloudflare.PurgeCacheRequest{
				Files: []string{
					"https://gortc.io/",
				},
			})
			if err != nil {
				log.Println("failed to purge cache:", err)
				return
			}
			if !res.Success {
				log.Println("failed to purge cache: not succeeded")
			} else {
				log.Println("purged cf cache")
			}
		}()
	})
	http.HandleFunc("/ice-configuration", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Add("Content-type", "application/json")
		encoder := json.NewEncoder(w)
		origin := r.Header.Get("Origin")
		server := "stun:gortc.io"
		if len(origin) > 0 {
			u, err := url.Parse(origin)
			if err != nil {
				log.Printf("http: failed to parse origin %q: %s", origin, err)
			} else {
				if idx := strings.LastIndex(u.Host, ":"); idx > 0 {
					u.Host = u.Host[:idx]
				}
				server = fmt.Sprintf("stun:%s:%d", u.Host, *portSTUN)
				log.Printf("http: sending ice-server %q for origin %q", server, origin)
			}
		}
		if err := encoder.Encode(iceConfiguration{
			Servers: []iceServerConfiguration{
				{URLs: []string{server}},
			},
		}); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintln(w, "json encode:", err)
		}
	})

	mLog, err := os.OpenFile("packets.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatalln("Failed to open log:", err)
	}
	defer mLog.Close()
	csvLog := csv.NewWriter(mLog)

	http.HandleFunc("/x/sdp", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		log.Println("http:", r.Method, "request from", r.RemoteAddr)
		if r.Method == http.MethodGet {
			http.Redirect(w, r, "/x/sdp/", http.StatusPermanentRedirect)
			return
		}
		s := sdp.Session{}
		data, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Println("http: ReadAll body failed:", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		if s, err = sdp.DecodeSession(data, s); err != nil {
			log.Println("http: failed to decode sdp session:", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		for k, v := range s {
			fmt.Fprintf(w, `<p class="attribute">%02d %s</p>`+"\n", k, v)
			if v.Type != sdp.TypeAttribute {
				continue
			}
			if !bytes.HasPrefix(v.Value, []byte("candidate")) {
				continue
			}
			c := new(ice.Candidate)
			fmt.Fprintln(w, `<div class="stun-message">`)
			if err = ice.ParseAttribute(v.Value, c); err != nil {
				fmt.Fprintln(w, `<p class="error">failed to parse as candidate:`, err, "
")
				fmt.Fprintln(w, `</div>`)
				continue
			}
			fmt.Fprintln(w, "
parsed as candidate:", fmt.Sprintf("%+v", c), "
")
			if c.Type != ice.CandidateServerReflexive {
				fmt.Fprintln(w, `</div>`)
				continue
			}
			addr := fmt.Sprintf("%s:%d", c.ConnectionAddress, c.Port)
			m := messages.pop(addr)
			if m == nil {
				log.Println("http: no message for", addr, "in log")
				fmt.Fprintln(w, `<p class="warning">message from candidate not found in STUN log</p>`)
				fmt.Fprintln(w, `</div>`)
				continue
			}
			fmt.Fprintln(w, `<p class="success">message found in STUN log:`, m, `</p>`)
			for _, a := range m.Attributes {
				switch a.Type {
				case stun.AttrOrigin:
					fmt.Fprintf(w, "
STUN attribute %s: %q (len=%d)
", a.Type, a.Value, a.Length)
				default:
					fmt.Fprintf(w, "
STUN attribute %s: %v (len=%d)
", a.Type, a.Value, a.Length)
				}
			}
			var (
				b64             = base64.StdEncoding.EncodeToString(m.Raw)
				messageCRC64    = crc64.Checksum(m.Raw, crc64.MakeTable(crc64.ISO))
				clipID          = fmt.Sprintf("crc64-%d", messageCRC64)
				ua              = user_agent.New(r.Header.Get("User-agent"))
				bName, bVersion = ua.Browser()
			)
			if err = csvLog.Write([]string{
				addr,
				b64,
				fmt.Sprintf("%d", messageCRC64),
				bName,
				bVersion,
				ua.OS(),
			}); err != nil {
				log.Fatalln("log: failed to write:", err)
			}
			csvLog.Flush()
			fmt.Fprintln(w, `<p>dumped: <code id="`+clipID+`">stun-decode`, b64, `
				<button class="btn" data-clipboard-target="#`+clipID+`">copy</button>

`)
			fmt.Fprintln(w, `<p>crc64: <code>`, messageCRC64, `</code></p>`)
			fmt.Fprintln(w, `</div>`)
		}
	})

	var (
		addrSTUN = fmt.Sprintf(":%d", *portSTUN)
		addrHTTP = fmt.Sprintf("%s:%d", *hostHTTP, *portHTTP)
	)
	log.Println("Listening udp", addrSTUN)
	c, err := net.ListenPacket("udp", addrSTUN)
	if err != nil {
		log.Fatalf("Failed to bind udp on %s: %s", addrSTUN, err)
	}
	defer c.Close()

	// spawning storage garbage collector
	go messages.gc()

	// spawning STUN server
	go func(conn net.PacketConn) {
		log.Println("Started STUN server on", conn.LocalAddr())
		var (
			res = new(stun.Message)
			req = new(stun.Message)
			buf = make([]byte, 1024)
		)
		for {
			// ReadFrom c to buf
			n, addr, err := c.ReadFrom(buf)
			if err != nil {
				log.Fatalln("c.ReadFrom:", err)
			}
			log.Printf("udp: got packet len(%d) from %s", n, addr)
			// processing binding request
			if err = processUDPPacket(addr, buf[:n], req, res); err != nil {
				log.Println("failed to process UDP packet:", err, "from addr", addr)
			} else {
				log.Printf("stun: parsed message %q from %s", req, addr)
				if _, err = c.WriteTo(res.Raw, addr); err != nil {
					log.Println("failed to send packet:", err)
				}
			}
			res.Reset()
			req.Reset()
		}

	}(c)
	log.Println("Listening http", addrHTTP)
	log.Fatal(http.ListenAndServe(addrHTTP, nil))
}
<commit_msg>all: trim triple dot<commit_after>package main

import (
	"bytes"
	"encoding/base64"
	"encoding/csv"
	"encoding/json"
	"flag"
	"fmt"
	"hash/crc64"
	"html/template"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/cloudflare/cloudflare-go"
	"github.com/gortc/ice"
	"github.com/gortc/sdp"
	"github.com/gortc/stun"
	"github.com/mssola/user_agent"
)

var (
	portHTTP = flag.Int("port", 3000, "http server port")
	hostHTTP = flag.String("host", "localhost", "http server host")
	portSTUN = flag.Int("port-stun", stun.DefaultPort, "UDP port")
)

var (
	bindingRequest = stun.MessageType{
		Method: stun.MethodBinding,
		Class:  stun.ClassRequest,
	}
	bindingSuccessResponse = stun.MessageType{
		Method: stun.MethodBinding,
		Class:  stun.ClassSuccessResponse,
	}
)

func processUDPPacket(addr net.Addr, b []byte, req, res *stun.Message) error {
	if !stun.IsMessage(b) {
		log.Println("packet from", addr, "is not STUN message")
		return nil
	}
	req.Raw = b
	if err := req.Decode(); err != nil {
		return err
	}
	if req.Type != bindingRequest {
		log.Println("stun: skipping", req.Type, "from", addr)
		return nil
	}
	log.Println("stun: got", req.Type)
	res.TransactionID = req.TransactionID
	res.Type = bindingSuccessResponse
	var (
		ip   net.IP
		port int
	)
	switch a := addr.(type) {
	case *net.UDPAddr:
		ip = a.IP
		port = a.Port
	default:
		panic(fmt.Sprintf("unknown addr: %v", addr))
	}
	stun.XORMappedAddress{
		IP:   ip,
		Port: port,
	}.AddTo(res)
	stun.NewSoftware("gortc.io/x/sdp example").AddTo(res)
	res.WriteHeader()
	messages.add(fmt.Sprintf("%s:%d", ip, port), req)
	return nil
}

type iceServerConfiguration struct {
	URLs []string `json:"urls"`
}

type iceConfiguration struct {
	Servers []iceServerConfiguration `json:"iceServers"`
}

func main() {
	flag.Parse()
	cf, err := cloudflare.New(
		os.Getenv("CF_API_KEY"),
		os.Getenv("CF_API_EMAIL"),
	)
	if err != nil {
		log.Fatal(err)
	}
	t, err := template.ParseFiles("static/index.html")
	if err != nil {
		log.Fatal(err)
	}
	log.SetFlags(log.Lshortfile)
	fs := http.FileServer(http.Dir("static"))
	var (
		s     *stats
		sLock sync.RWMutex
	)
	go func() {
		sLock.Lock()
		log.Println("gettings stats")
		s, err = getStats(false)
		if err != nil {
			log.Println("failed to get stats:", err)
		} else {
			log.Println("got stats")
		}
		sLock.Unlock()
	}()
	update := func() error {
		log.Println("updating stats")
		newStats, err := getStats(true)
		if err != nil {
			log.Println("failed to fetch stats:", err)
			return err
		}
		sLock.Lock()
		s = newStats
		sLock.Unlock()
		return nil
	}
	go func() {
		ticker := time.NewTicker(time.Second * 90)
		for range ticker.C {
			_ = update()
		}
	}()
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		q := r.URL.Query()
		// path: /foo
		//       /foo/...
		// package: foo
		pkg := strings.TrimPrefix(r.URL.Path, "/")
		if i := strings.Index(pkg, "/"); i != -1 {
			pkg = pkg[:i]
		}
		pkg = strings.TrimSuffix(pkg, "...")

		if q.Get("go-get") == "1" && pkg != "" {
			// Custom domain support.
			// TODO: Check github org.
			body := strings.Replace(`<!DOCTYPE html>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="go-import" content="gortc.io/pkg git https://github.com/gortc/pkg.git">
    <meta name="go-source"
          content="gortc.io/pkg https://github.com/gortc/pkg/ https://github.com/gortc/pkg/tree/master{/dir} https://github.com/gortc/pkg/blob/master{/dir}/{file}#L{line}">
    <meta http-equiv="refresh" content="0; url=https://godoc.org/gortc.io/pkg">

Nothing to see here; move along.
`, "pkg", pkg, -1)
			fmt.Fprintln(w, body)
			return
		}
		if r.URL.Path != "/" {
			fs.ServeHTTP(w, r)
			return
		}
		w.Header().Add("Link", "</go-rtc.svg>; as=image; rel=preload")
		w.Header().Add("Link", "</jetbrains-variant-3.svg>; as=image; rel=preload")
		w.Header().Add("Link", "</css/main.css>; as=style; rel=preload")
		sLock.RLock()
		if err := t.Execute(w, s); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintln(w, err)
		}
		sLock.RUnlock()
	})
	http.HandleFunc("/hook/"+os.Getenv("GITHUB_HOOK_SECRET"), func(writer http.ResponseWriter, request *http.Request) {
		start := time.Now()
		err := update()
		if err != nil {
			writer.WriteHeader(http.StatusInternalServerError)
			fmt.Println(writer, "failed:", err)
			return
		}
		writer.WriteHeader(http.StatusOK)
		fmt.Fprintln(writer, "updated in", time.Since(start))
		go func() {
			log.Println("purging cf cache")
			zoneID, err := cf.ZoneIDByName("gortc.io")
			if err != nil {
				log.Println("failed to get zone id:", err)
				return
			}
			res, err := cf.PurgeCache(zoneID, cloudflare.PurgeCacheRequest{
				Files: []string{
					"https://gortc.io/",
				},
			})
			if err != nil {
				log.Println("failed to purge cache:", err)
				return
			}
			if !res.Success {
				log.Println("failed to purge cache: not succeeded")
			} else {
				log.Println("purged cf cache")
			}
		}()
	})
	http.HandleFunc("/ice-configuration", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Add("Content-type", "application/json")
		encoder := json.NewEncoder(w)
		origin := r.Header.Get("Origin")
		server := "stun:gortc.io"
		if len(origin) > 0 {
			u, err := url.Parse(origin)
			if err != nil {
				log.Printf("http: failed to parse origin %q: %s", origin, err)
			} else {
				if idx := strings.LastIndex(u.Host, ":"); idx > 0 {
					u.Host = u.Host[:idx]
				}
				server = fmt.Sprintf("stun:%s:%d", u.Host, *portSTUN)
				log.Printf("http: sending ice-server %q for origin %q", server, origin)
			}
		}
		if err := encoder.Encode(iceConfiguration{
			Servers: []iceServerConfiguration{
				{URLs: []string{server}},
			},
		}); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintln(w, "json encode:", err)
		}
	})

	mLog, err := os.OpenFile("packets.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatalln("Failed to open log:", err)
	}
	defer mLog.Close()
	csvLog := csv.NewWriter(mLog)

	http.HandleFunc("/x/sdp", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		log.Println("http:", r.Method, "request from", r.RemoteAddr)
		if r.Method == http.MethodGet {
			http.Redirect(w, r, "/x/sdp/", http.StatusPermanentRedirect)
			return
		}
		s := sdp.Session{}
		data, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Println("http: ReadAll body failed:", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		if s, err = sdp.DecodeSession(data, s); err != nil {
			log.Println("http: failed to decode sdp session:", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		for k, v := range s {
			fmt.Fprintf(w, `<p class="attribute">%02d %s</p>`+"\n", k, v)
			if v.Type != sdp.TypeAttribute {
				continue
			}
			if !bytes.HasPrefix(v.Value, []byte("candidate")) {
				continue
			}
			c := new(ice.Candidate)
			fmt.Fprintln(w, `<div class="stun-message">`)
			if err = ice.ParseAttribute(v.Value, c); err != nil {
				fmt.Fprintln(w, `<p class="error">failed to parse as candidate:`, err, "
")
				fmt.Fprintln(w, `</div>`)
				continue
			}
			fmt.Fprintln(w, "
parsed as candidate:", fmt.Sprintf("%+v", c), "
")
			if c.Type != ice.CandidateServerReflexive {
				fmt.Fprintln(w, `</div>`)
				continue
			}
			addr := fmt.Sprintf("%s:%d", c.ConnectionAddress, c.Port)
			m := messages.pop(addr)
			if m == nil {
				log.Println("http: no message for", addr, "in log")
				fmt.Fprintln(w, `<p class="warning">message from candidate not found in STUN log</p>`)
				fmt.Fprintln(w, `</div>`)
				continue
			}
			fmt.Fprintln(w, `<p class="success">message found in STUN log:`, m, `</p>`)
			for _, a := range m.Attributes {
				switch a.Type {
				case stun.AttrOrigin:
					fmt.Fprintf(w, "
STUN attribute %s: %q (len=%d)
", a.Type, a.Value, a.Length)
				default:
					fmt.Fprintf(w, "
STUN attribute %s: %v (len=%d)
", a.Type, a.Value, a.Length)
				}
			}
			var (
				b64             = base64.StdEncoding.EncodeToString(m.Raw)
				messageCRC64    = crc64.Checksum(m.Raw, crc64.MakeTable(crc64.ISO))
				clipID          = fmt.Sprintf("crc64-%d", messageCRC64)
				ua              = user_agent.New(r.Header.Get("User-agent"))
				bName, bVersion = ua.Browser()
			)
			if err = csvLog.Write([]string{
				addr,
				b64,
				fmt.Sprintf("%d", messageCRC64),
				bName,
				bVersion,
				ua.OS(),
			}); err != nil {
				log.Fatalln("log: failed to write:", err)
			}
			csvLog.Flush()
			fmt.Fprintln(w, `<p>dumped: <code id="`+clipID+`">stun-decode`, b64, `
				<button class="btn" data-clipboard-target="#`+clipID+`">copy</button>

`)
			fmt.Fprintln(w, `<p>crc64: <code>`, messageCRC64, `</code></p>`)
			fmt.Fprintln(w, `</div>`)
		}
	})

	var (
		addrSTUN = fmt.Sprintf(":%d", *portSTUN)
		addrHTTP = fmt.Sprintf("%s:%d", *hostHTTP, *portHTTP)
	)
	log.Println("Listening udp", addrSTUN)
	c, err := net.ListenPacket("udp", addrSTUN)
	if err != nil {
		log.Fatalf("Failed to bind udp on %s: %s", addrSTUN, err)
	}
	defer c.Close()

	// spawning storage garbage collector
	go messages.gc()

	// spawning STUN server
	go func(conn net.PacketConn) {
		log.Println("Started STUN server on", conn.LocalAddr())
		var (
			res = new(stun.Message)
			req = new(stun.Message)
			buf = make([]byte, 1024)
		)
		for {
			// ReadFrom c to buf
			n, addr, err := c.ReadFrom(buf)
			if err != nil {
				log.Fatalln("c.ReadFrom:", err)
			}
			log.Printf("udp: got packet len(%d) from %s", n, addr)
			// processing binding request
			if err = processUDPPacket(addr, buf[:n], req, res); err != nil {
				log.Println("failed to process UDP packet:", err, "from addr", addr)
			} else {
				log.Printf("stun: parsed message %q from %s", req, addr)
				if _, err = c.WriteTo(res.Raw, addr); err != nil {
					log.Println("failed to send packet:", err)
				}
			}
			res.Reset()
			req.Reset()
		}

	}(c)
	log.Println("Listening http", addrHTTP)
	log.Fatal(http.ListenAndServe(addrHTTP, nil))
}
<|endoftext|>


<commit_before>package main

import (
  "fbtron/fbtron"

  "fmt"
  "runtime"
  "time"
)

func main() {
  fmt.Println("Starting")
  start_time := time.Now()

  // Tell Go to use all of the processors
  num_cpus := runtime.NumCPU()
  runtime.GOMAXPROCS(num_cpus)

  sendchannels := make([]chan string, num_cpus)
  recvchannels := make([]chan fbtron.Simulation, num_cpus)
  for n := range sendchannels {
    sendchannels[n] = make(chan string, 1)
    recvchannels[n] = make(chan fbtron.Simulation, 1)
    go fbtron.RunSimulation(sendchannels[n], recvchannels[n])
  }

  // TODO: Start http thread ...

  // TEMP
  for {
    time.Sleep(time.Second * 1)

    for n := range sendchannels {
      sendchannels[n] <- "ping"
      response := <-recvchannels[n]
      fmt.Println("Got response from simulation thread %d: ran %d seasons",
                  n, response.Num_seasons)
    }

    if time.Since(start_time) > time.Second * 10 {
      fmt.Println("Shutting down all threads")
      for n := range sendchannels {
        sendchannels[n] <- "quitquitquit"
      }
      break
    }
  }
}
<commit_msg>Duh Println doesn't use a format string<commit_after>package main

import (
  "fbtron/fbtron"

  "fmt"
  "runtime"
  "time"
)

func main() {
  fmt.Println("Starting")
  start_time := time.Now()

  // Tell Go to use all of the processors
  num_cpus := runtime.NumCPU()
  runtime.GOMAXPROCS(num_cpus)

  sendchannels := make([]chan string, num_cpus)
  recvchannels := make([]chan fbtron.Simulation, num_cpus)
  for n := range sendchannels {
    sendchannels[n] = make(chan string, 1)
    recvchannels[n] = make(chan fbtron.Simulation, 1)
    go fbtron.RunSimulation(sendchannels[n], recvchannels[n])
  }

  // TODO: Start http thread ...

  // TEMP
  for {
    time.Sleep(time.Second * 1)

    for n := range sendchannels {
      sendchannels[n] <- "ping"
      response := <-recvchannels[n]
      fmt.Printf("Got response from simulation thread %d: ran %d seasons\n",
                  n, response.Num_seasons)
    }

    if time.Since(start_time) > time.Second * 10 {
      fmt.Println("Shutting down all threads")
      for n := range sendchannels {
        sendchannels[n] <- "quitquitquit"
      }
      break
    }
  }
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/jingweno/nut/vendor/_nuts/github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "nut"
	app.Usage = "Vendor Go dependencies"
	app.Version = "0.0.1"
	app.Author = ""
	app.Email = ""

	app.Commands = []cli.Command{
		installCmd,
		listCmd,
		newCmd,
	}

	app.Run(os.Args)
}

func check(err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Remove list command for now<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/jingweno/nut/vendor/_nuts/github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "nut"
	app.Usage = "Vendor Go dependencies"
	app.Version = "0.0.1"
	app.Author = ""
	app.Email = ""

	app.Commands = []cli.Command{
		installCmd,
		newCmd,
	}

	app.Run(os.Args)
}

func check(err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>