<commit_before>package in_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"

	"github.com/ljfranklin/terraform-resource/in"
	"github.com/ljfranklin/terraform-resource/models"
	"github.com/ljfranklin/terraform-resource/out"
	"github.com/ljfranklin/terraform-resource/test/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("JSON Plan", func() {

	var (
		backendType   string
		backendConfig map[string]interface{}
		envName       string
		stateFilePath string
		planFilePath  string
		s3ObjectPath  string
		workingDir    string
		inDir         string
		workspacePath string
		awsVerifier   *helpers.AWSVerifier
		accessKey     string
		secretKey     string
		bucket        string
		bucketPath    string
		region        string
	)

	BeforeEach(func() {
		accessKey = os.Getenv("AWS_ACCESS_KEY")
		Expect(accessKey).ToNot(BeEmpty(), "AWS_ACCESS_KEY must be set")
		secretKey = os.Getenv("AWS_SECRET_KEY")
		Expect(secretKey).ToNot(BeEmpty(), "AWS_SECRET_KEY must be set")
		bucket = os.Getenv("AWS_BUCKET")
		Expect(bucket).ToNot(BeEmpty(), "AWS_BUCKET must be set")
		bucketPath = os.Getenv("AWS_BUCKET_SUBFOLDER")
		Expect(bucketPath).ToNot(BeEmpty(), "AWS_BUCKET_SUBFOLDER must be set")

		region = os.Getenv("AWS_REGION") // optional
		if region == "" {
			region = "us-east-1"
		}

		awsVerifier = helpers.NewAWSVerifier(
			accessKey,
			secretKey,
			region,
			"",
		)

		region := os.Getenv("AWS_REGION") // optional
		if region == "" {
			region = "us-east-1"
		}

		workspacePath = helpers.RandomString("out-backend-test")

		envName = helpers.RandomString("out-test")
		stateFilePath = path.Join(workspacePath, envName, "terraform.tfstate")
		planFilePath = path.Join(workspacePath, fmt.Sprintf("%s-plan", envName), "terraform.tfstate")
		s3ObjectPath = path.Join(bucketPath, helpers.RandomString("out-test"))

		backendType = "s3"
		backendConfig = map[string]interface{}{
			"bucket":               bucket,
			"key":                  "terraform.tfstate",
			"access_key":           accessKey,
			"secret_key":           secretKey,
			"region":               region,
			"workspace_key_prefix": workspacePath,
		}

		var err error
		workingDir, err = ioutil.TempDir(os.TempDir(), "terraform-resource-out-test")
		Expect(err).ToNot(HaveOccurred())

		inDir, err = ioutil.TempDir(os.TempDir(), "terraform-resource-in-test")
		Expect(err).ToNot(HaveOccurred())

		// ensure relative paths resolve correctly
		err = os.Chdir(workingDir)
		Expect(err).ToNot(HaveOccurred())

		fixturesDir := path.Join(helpers.ProjectRoot(), "fixtures")
		err = exec.Command("cp", "-r", fixturesDir, workingDir).Run()
		Expect(err).ToNot(HaveOccurred())

		err = helpers.DownloadStatefulPlugin(workingDir)
		Expect(err).ToNot(HaveOccurred())
	})

	AfterEach(func() {
		_ = os.RemoveAll(workingDir)
		_ = os.RemoveAll(inDir)
		awsVerifier.DeleteObjectFromS3(bucket, s3ObjectPath)
		awsVerifier.DeleteObjectFromS3(bucket, planFilePath)
		awsVerifier.DeleteObjectFromS3(bucket, stateFilePath)
	})

	It("plan infrastructure and test it without plan output", func() {
		planOutRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source:   "fixtures/aws/",
					PlanOnly: true,
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		By("running 'out' to create the plan file")

		planrunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		planOutput, err := planrunner.Run(planOutRequest)
		Expect(err).ToNot(HaveOccurred())

		By("ensuring that plan file exists")

		awsVerifier.ExpectS3FileToExist(
			bucket,
			planFilePath,
		)
		defer awsVerifier.DeleteObjectFromS3(bucket, planFilePath)

		Expect(planOutput.Version.EnvName).To(Equal(planOutRequest.Params.EnvName))
		Expect(planOutput.Version.PlanOnly).To(Equal("true"), "Expected PlanOnly to be true, but was false")
		Expect(planOutput.Version.Serial).To(BeEmpty())
		Expect(planOutput.Version.PlanChecksum).To(MatchRegexp("[0-9|a-f]+"))

		By("does not output the planfile if `output_planfile` is not given")

		inReq := models.InRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					Source: ".",
					Env: map[string]string{
						"HOME": inDir,
					},
					BackendType: "s3",
					BackendConfig: map[string]interface{}{
						"bucket":               bucket,
						"key":                  "terraform.tfstate",
						"access_key":           accessKey,
						"secret_key":           secretKey,
						"region":               region,
						"workspace_key_prefix": workspacePath,
					},
				},
			},
			Version: planOutput.Version,
			Params: models.InParams{
				OutputJSONPlanfile: false,
			},
		}

		runner := in.Runner{
			OutputDir: inDir,
		}
		_, err = runner.Run(inReq)
		Expect(err).ToNot(HaveOccurred())

		expectedNamePath := path.Join(inDir, "name")
		Expect(expectedNamePath).To(BeAnExistingFile())

		expectedPlanPath := path.Join(inDir, "plan.json")
		Expect(expectedPlanPath).ToNot(BeAnExistingFile())
	})

	It("plan infrastructure and test it", func() {
		planOutRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source:   "fixtures/aws/",
					PlanOnly: true,
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		By("running 'out' to create the plan file")

		planrunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		planOutput, err := planrunner.Run(planOutRequest)
		Expect(err).ToNot(HaveOccurred())

		By("outputs the planfile if `output_planfile` is given")

		inReq := models.InRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					Source: ".",
					Env: map[string]string{
						"HOME": inDir,
					},
					BackendType: "s3",
					BackendConfig: map[string]interface{}{
						"bucket":               bucket,
						"key":                  "terraform.tfstate",
						"access_key":           accessKey,
						"secret_key":           secretKey,
						"region":               region,
						"workspace_key_prefix": workspacePath,
					},
				},
			},
			Version: planOutput.Version,
			Params: models.InParams{
				OutputJSONPlanfile: true,
			},
		}

		runner := in.Runner{
			OutputDir: inDir,
		}
		_, err = runner.Run(inReq)
		Expect(err).ToNot(HaveOccurred())

		expectedNamePath := path.Join(inDir, "name")
		Expect(expectedNamePath).To(BeAnExistingFile())

		expectedPlanPath := path.Join(inDir, "plan.json")
		Expect(expectedPlanPath).To(BeAnExistingFile())

		stateContents, err := ioutil.ReadFile(expectedPlanPath)
		Expect(err).To(BeNil())
		Expect(string(stateContents)).To(ContainSubstring("variables"))
		Expect(string(stateContents)).To(ContainSubstring("output_changes"))
		Expect(string(stateContents)).To(ContainSubstring("resource_changes"))
		Expect(string(stateContents)).To(ContainSubstring("\"format_version\":\"0.1\""))
	})

	It("HACK: outputs metadata file if statefile exists", func() {
		planApplyRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source: "fixtures/aws/",
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		applyRunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		_, err := applyRunner.Run(planApplyRequest)
		Expect(err).ToNot(HaveOccurred())

		planOutRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source:   "fixtures/aws/",
					PlanOnly: true,
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		planrunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		planOutput, err := planrunner.Run(planOutRequest)
		Expect(err).ToNot(HaveOccurred())

		inReq := models.InRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					Source: ".",
					Env: map[string]string{
						"HOME": inDir,
					},
					BackendType: "s3",
					BackendConfig: map[string]interface{}{
						"bucket":               bucket,
						"key":                  "terraform.tfstate",
						"access_key":           accessKey,
						"secret_key":           secretKey,
						"region":               region,
						"workspace_key_prefix": workspacePath,
					},
				},
			},
			Version: planOutput.Version,
			Params:  models.InParams{},
		}

		runner := in.Runner{
			OutputDir: inDir,
		}
		_, err = runner.Run(inReq)
		Expect(err).ToNot(HaveOccurred())

		expectedOutputPath := path.Join(inDir, "metadata")
		Expect(expectedOutputPath).To(BeAnExistingFile())
		outputFile, err := os.Open(expectedOutputPath)
		Expect(err).ToNot(HaveOccurred())
		defer outputFile.Close()

		outputContents := map[string]interface{}{}
		err = json.NewDecoder(outputFile).Decode(&outputContents)
		Expect(err).ToNot(HaveOccurred())

		Expect(outputContents).NotTo(BeEmpty())
	})
})
<commit_msg>Remove brittle test assertion<commit_after>package in_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"

	"github.com/ljfranklin/terraform-resource/in"
	"github.com/ljfranklin/terraform-resource/models"
	"github.com/ljfranklin/terraform-resource/out"
	"github.com/ljfranklin/terraform-resource/test/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("JSON Plan", func() {

	var (
		backendType   string
		backendConfig map[string]interface{}
		envName       string
		stateFilePath string
		planFilePath  string
		s3ObjectPath  string
		workingDir    string
		inDir         string
		workspacePath string
		awsVerifier   *helpers.AWSVerifier
		accessKey     string
		secretKey     string
		bucket        string
		bucketPath    string
		region        string
	)

	BeforeEach(func() {
		accessKey = os.Getenv("AWS_ACCESS_KEY")
		Expect(accessKey).ToNot(BeEmpty(), "AWS_ACCESS_KEY must be set")
		secretKey = os.Getenv("AWS_SECRET_KEY")
		Expect(secretKey).ToNot(BeEmpty(), "AWS_SECRET_KEY must be set")
		bucket = os.Getenv("AWS_BUCKET")
		Expect(bucket).ToNot(BeEmpty(), "AWS_BUCKET must be set")
		bucketPath = os.Getenv("AWS_BUCKET_SUBFOLDER")
		Expect(bucketPath).ToNot(BeEmpty(), "AWS_BUCKET_SUBFOLDER must be set")

		region = os.Getenv("AWS_REGION") // optional
		if region == "" {
			region = "us-east-1"
		}

		awsVerifier = helpers.NewAWSVerifier(
			accessKey,
			secretKey,
			region,
			"",
		)

		region := os.Getenv("AWS_REGION") // optional
		if region == "" {
			region = "us-east-1"
		}

		workspacePath = helpers.RandomString("out-backend-test")

		envName = helpers.RandomString("out-test")
		stateFilePath = path.Join(workspacePath, envName, "terraform.tfstate")
		planFilePath = path.Join(workspacePath, fmt.Sprintf("%s-plan", envName), "terraform.tfstate")
		s3ObjectPath = path.Join(bucketPath, helpers.RandomString("out-test"))

		backendType = "s3"
		backendConfig = map[string]interface{}{
			"bucket":               bucket,
			"key":                  "terraform.tfstate",
			"access_key":           accessKey,
			"secret_key":           secretKey,
			"region":               region,
			"workspace_key_prefix": workspacePath,
		}

		var err error
		workingDir, err = ioutil.TempDir(os.TempDir(), "terraform-resource-out-test")
		Expect(err).ToNot(HaveOccurred())

		inDir, err = ioutil.TempDir(os.TempDir(), "terraform-resource-in-test")
		Expect(err).ToNot(HaveOccurred())

		// ensure relative paths resolve correctly
		err = os.Chdir(workingDir)
		Expect(err).ToNot(HaveOccurred())

		fixturesDir := path.Join(helpers.ProjectRoot(), "fixtures")
		err = exec.Command("cp", "-r", fixturesDir, workingDir).Run()
		Expect(err).ToNot(HaveOccurred())

		err = helpers.DownloadStatefulPlugin(workingDir)
		Expect(err).ToNot(HaveOccurred())
	})

	AfterEach(func() {
		_ = os.RemoveAll(workingDir)
		_ = os.RemoveAll(inDir)
		awsVerifier.DeleteObjectFromS3(bucket, s3ObjectPath)
		awsVerifier.DeleteObjectFromS3(bucket, planFilePath)
		awsVerifier.DeleteObjectFromS3(bucket, stateFilePath)
	})

	It("plan infrastructure and test it without plan output", func() {
		planOutRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source:   "fixtures/aws/",
					PlanOnly: true,
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		By("running 'out' to create the plan file")

		planrunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		planOutput, err := planrunner.Run(planOutRequest)
		Expect(err).ToNot(HaveOccurred())

		By("ensuring that plan file exists")

		awsVerifier.ExpectS3FileToExist(
			bucket,
			planFilePath,
		)
		defer awsVerifier.DeleteObjectFromS3(bucket, planFilePath)

		Expect(planOutput.Version.EnvName).To(Equal(planOutRequest.Params.EnvName))
		Expect(planOutput.Version.PlanOnly).To(Equal("true"), "Expected PlanOnly to be true, but was false")
		Expect(planOutput.Version.Serial).To(BeEmpty())
		Expect(planOutput.Version.PlanChecksum).To(MatchRegexp("[0-9|a-f]+"))

		By("does not output the planfile if `output_planfile` is not given")

		inReq := models.InRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					Source: ".",
					Env: map[string]string{
						"HOME": inDir,
					},
					BackendType: "s3",
					BackendConfig: map[string]interface{}{
						"bucket":               bucket,
						"key":                  "terraform.tfstate",
						"access_key":           accessKey,
						"secret_key":           secretKey,
						"region":               region,
						"workspace_key_prefix": workspacePath,
					},
				},
			},
			Version: planOutput.Version,
			Params: models.InParams{
				OutputJSONPlanfile: false,
			},
		}

		runner := in.Runner{
			OutputDir: inDir,
		}
		_, err = runner.Run(inReq)
		Expect(err).ToNot(HaveOccurred())

		expectedNamePath := path.Join(inDir, "name")
		Expect(expectedNamePath).To(BeAnExistingFile())

		expectedPlanPath := path.Join(inDir, "plan.json")
		Expect(expectedPlanPath).ToNot(BeAnExistingFile())
	})

	It("plan infrastructure and test it", func() {
		planOutRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source:   "fixtures/aws/",
					PlanOnly: true,
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		By("running 'out' to create the plan file")

		planrunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		planOutput, err := planrunner.Run(planOutRequest)
		Expect(err).ToNot(HaveOccurred())

		By("outputs the planfile if `output_planfile` is given")

		inReq := models.InRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					Source: ".",
					Env: map[string]string{
						"HOME": inDir,
					},
					BackendType: "s3",
					BackendConfig: map[string]interface{}{
						"bucket":               bucket,
						"key":                  "terraform.tfstate",
						"access_key":           accessKey,
						"secret_key":           secretKey,
						"region":               region,
						"workspace_key_prefix": workspacePath,
					},
				},
			},
			Version: planOutput.Version,
			Params: models.InParams{
				OutputJSONPlanfile: true,
			},
		}

		runner := in.Runner{
			OutputDir: inDir,
		}
		_, err = runner.Run(inReq)
		Expect(err).ToNot(HaveOccurred())

		expectedNamePath := path.Join(inDir, "name")
		Expect(expectedNamePath).To(BeAnExistingFile())

		expectedPlanPath := path.Join(inDir, "plan.json")
		Expect(expectedPlanPath).To(BeAnExistingFile())

		stateContents, err := ioutil.ReadFile(expectedPlanPath)
		Expect(err).To(BeNil())
		Expect(string(stateContents)).To(ContainSubstring("variables"))
		Expect(string(stateContents)).To(ContainSubstring("output_changes"))
		Expect(string(stateContents)).To(ContainSubstring("resource_changes"))
	})

	It("HACK: outputs metadata file if statefile exists", func() {
		planApplyRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source: "fixtures/aws/",
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		applyRunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		_, err := applyRunner.Run(planApplyRequest)
		Expect(err).ToNot(HaveOccurred())

		planOutRequest := models.OutRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					BackendType:   backendType,
					BackendConfig: backendConfig,
				},
			},
			Params: models.OutParams{
				EnvName: envName,
				Terraform: models.Terraform{
					Source:   "fixtures/aws/",
					PlanOnly: true,
					Env: map[string]string{
						"HOME": workingDir, // in prod plugin is installed system-wide
					},
					Vars: map[string]interface{}{
						"access_key":     accessKey,
						"secret_key":     secretKey,
						"bucket":         bucket,
						"object_key":     s3ObjectPath,
						"object_content": "terraform-is-neat",
						"region":         region,
					},
				},
			},
		}

		planrunner := out.Runner{
			SourceDir: workingDir,
			LogWriter: GinkgoWriter,
		}
		planOutput, err := planrunner.Run(planOutRequest)
		Expect(err).ToNot(HaveOccurred())

		inReq := models.InRequest{
			Source: models.Source{
				Terraform: models.Terraform{
					Source: ".",
					Env: map[string]string{
						"HOME": inDir,
					},
					BackendType: "s3",
					BackendConfig: map[string]interface{}{
						"bucket":               bucket,
						"key":                  "terraform.tfstate",
						"access_key":           accessKey,
						"secret_key":           secretKey,
						"region":               region,
						"workspace_key_prefix": workspacePath,
					},
				},
			},
			Version: planOutput.Version,
			Params:  models.InParams{},
		}

		runner := in.Runner{
			OutputDir: inDir,
		}
		_, err = runner.Run(inReq)
		Expect(err).ToNot(HaveOccurred())

		expectedOutputPath := path.Join(inDir, "metadata")
		Expect(expectedOutputPath).To(BeAnExistingFile())
		outputFile, err := os.Open(expectedOutputPath)
		Expect(err).ToNot(HaveOccurred())
		defer outputFile.Close()

		outputContents := map[string]interface{}{}
		err = json.NewDecoder(outputFile).Decode(&outputContents)
		Expect(err).ToNot(HaveOccurred())

		Expect(outputContents).NotTo(BeEmpty())
	})
})
<|endoftext|>


<commit_before>// Copyright 2015 The go-python 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 bind

import (
	"golang.org/x/tools/go/types"
)

type Var struct {
	Var   *types.Var
	dtype typedesc
}

func newVars(tuple *types.Tuple) []*Var {
	vars := make([]*Var, 0, tuple.Len())
	for i := 0; i < tuple.Len(); i++ {
		vars = append(vars, newVar(tuple.At(i)))
	}
	return vars
}

func newVar(v *types.Var) *Var {
	vv := &Var{
		Var: v,
	}
	switch typ := v.Type().(type) {
	case *types.Basic:
		dtype, ok := typedescr[typ.Kind()]
		if ok {
			vv.dtype = dtype
		}
	}
	return vv
}

func (v *Var) GoType() types.Type {
	return v.Var.Type()
}

func (v *Var) CType() string {
	return v.dtype.ctype
}

func (v *Var) CGoType() string {
	return v.dtype.cgotype
}

func (v *Var) PyCode() string {
	return v.dtype.pyfmt
}

func (v *Var) isGoString() bool {
	switch typ := v.GoType().(type) {
	case *types.Basic:
		return typ.Kind() == types.String
	}
	return false
}

func (v *Var) genDecl(g *cpyGen) {
	if v.isGoString() {
		g.Printf("const char* cgopy_%s;\n", v.Var.Name())
	}
	g.Printf("%[1]s c_%[2]s;\n", v.CGoType(), v.Var.Name())
}

func (v *Var) genRetDecl(g *cpyGen) {
	if v.isGoString() {
		g.Printf("const char* cgopy_gopy_ret;\n")
	}
	g.Printf("%[1]s c_gopy_ret;\n", v.CGoType())
}

func (v *Var) getArgParse() (string, string) {
	addr := "&c_" + v.Var.Name()
	if v.isGoString() {
		addr = "(GoString*)(&cgopy_" + v.Var.Name() + ")"
	}
	return v.dtype.pyfmt, addr
}

func (v *Var) genFuncPreamble(g *cpyGen) {
	if v.isGoString() {
		g.Printf("c_%[1]s = _cgopy_makegostring(cgopy_%[1]s);\n", v.Var.Name())
	}
}

func (v *Var) getFuncArg() string {
	return "c_" + v.Var.Name()
}
<commit_msg>py/bind: dont pass GoStrings to PyArg_ParseTuple<commit_after>// Copyright 2015 The go-python 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 bind

import (
	"golang.org/x/tools/go/types"
)

type Var struct {
	Var   *types.Var
	dtype typedesc
}

func newVars(tuple *types.Tuple) []*Var {
	vars := make([]*Var, 0, tuple.Len())
	for i := 0; i < tuple.Len(); i++ {
		vars = append(vars, newVar(tuple.At(i)))
	}
	return vars
}

func newVar(v *types.Var) *Var {
	vv := &Var{
		Var: v,
	}
	switch typ := v.Type().(type) {
	case *types.Basic:
		dtype, ok := typedescr[typ.Kind()]
		if ok {
			vv.dtype = dtype
		}
	}
	return vv
}

func (v *Var) GoType() types.Type {
	return v.Var.Type()
}

func (v *Var) CType() string {
	return v.dtype.ctype
}

func (v *Var) CGoType() string {
	return v.dtype.cgotype
}

func (v *Var) PyCode() string {
	return v.dtype.pyfmt
}

func (v *Var) isGoString() bool {
	switch typ := v.GoType().(type) {
	case *types.Basic:
		return typ.Kind() == types.String
	}
	return false
}

func (v *Var) genDecl(g *cpyGen) {
	if v.isGoString() {
		g.Printf("const char* cgopy_%s;\n", v.Var.Name())
	}
	g.Printf("%[1]s c_%[2]s;\n", v.CGoType(), v.Var.Name())
}

func (v *Var) genRetDecl(g *cpyGen) {
	if v.isGoString() {
		g.Printf("const char* cgopy_gopy_ret;\n")
	}
	g.Printf("%[1]s c_gopy_ret;\n", v.CGoType())
}

func (v *Var) getArgParse() (string, string) {
	addr := "&c_" + v.Var.Name()
	if v.isGoString() {
		addr = "&cgopy_" + v.Var.Name()
	}
	return v.dtype.pyfmt, addr
}

func (v *Var) genFuncPreamble(g *cpyGen) {
	if v.isGoString() {
		g.Printf("c_%[1]s = _cgopy_makegostring(cgopy_%[1]s);\n", v.Var.Name())
	}
}

func (v *Var) getFuncArg() string {
	return "c_" + v.Var.Name()
}
<|endoftext|>


<commit_before>package plugins

import (
	"strings"

	"encoding/json"

	"fmt"

	"time"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Seklfreak/Robyul2/metrics"
	"github.com/bwmarrin/discordgo"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

type perspectiveAction func(args []string, in *discordgo.Message, out **discordgo.MessageSend) (next perspectiveAction)

type Perspective struct {
	googleApiKey  string
	guildsToCheck []string
}

const (
	PerspectiveThreshold = 0.75
)

func (m *Perspective) Commands() []string {
	return []string{
		"perspective",
	}
}

func (m *Perspective) Init(session *discordgo.Session) {
	m.googleApiKey = helpers.GetConfig().Path("google.api_key").Data().(string)
	go func() {
		defer helpers.Recover()

		time.Sleep(60 * time.Second)
		err := m.cacheGuildsToCheck()
		helpers.Relax(err)
		m.logger().Info("initialised guilds to check cache")
	}()
}

func (m *Perspective) Uninit(session *discordgo.Session) {

}

func (m *Perspective) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	defer helpers.Recover()

	session.ChannelTyping(msg.ChannelID)

	var result *discordgo.MessageSend
	args := strings.Fields(content)

	action := m.actionStart
	for action != nil {
		action = action(args, msg, &result)
	}
}

func (m *Perspective) actionStart(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	cache.GetSession().ChannelTyping(in.ChannelID)

	if len(args) < 1 {
		*out = m.newMsg("bot.arguments.too-few")
		return m.actionFinish
	}

	switch args[0] {
	case "participate":
		return m.actionParticipate
	}

	return m.actionTest
}

// [p]perspective <message>
func (m *Perspective) actionTest(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	message := strings.TrimSpace(strings.Replace(in.Content, strings.Split(in.Content, " ")[0], "", 1))

	start := time.Now()
	severeToxicity, inflammatory, obscene, err := m.analyze(message)
	helpers.Relax(err)
	took := time.Since(start)

	var severeToxicityWarning, inflammatoryWarning, obsceneWarning string
	if severeToxicity >= PerspectiveThreshold {
		severeToxicityWarning = " ⚠"
	}
	if inflammatory >= PerspectiveThreshold {
		inflammatoryWarning = " ⚠"
	}
	if obscene >= PerspectiveThreshold {
		obsceneWarning = " ⚠"
	}

	*out = m.newMsg(fmt.Sprintf(
		"Severe Toxicity: %.2f%s, Inflammatory: %.2f%s, Obscene %.2f%s\nTook %s",
		severeToxicity, severeToxicityWarning,
		inflammatory, inflammatoryWarning,
		obscene, obsceneWarning,
		took.String(),
	))
	return m.actionFinish
}

// [p]perspective participate [<#channel or channel id>]
func (m *Perspective) actionParticipate(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	if !helpers.IsRobyulMod(in.Author.ID) {
		*out = m.newMsg("robyulmod.no_permission")
		return m.actionFinish
	}
	if !helpers.IsAdmin(in) {
		*out = m.newMsg("admin.no_permission")
		return m.actionFinish
	}

	channel, err := helpers.GetChannel(in.ChannelID)
	helpers.Relax(err)

	settings := helpers.GuildSettingsGetCached(channel.GuildID)

	if settings.PerspectiveIsParticipating && len(args) < 2 {
		// disable perspective checking
		settings.PerspectiveIsParticipating = false
		settings.PerspectiveChannelID = ""
		*out = m.newMsg("plugins.perspective.participation-disabled")
	} else {
		// enable perspective checking
		if len(args) < 2 {
			*out = m.newMsg("bot.arguments.too-few")
			return m.actionFinish
		}

		targetChannel, err := helpers.GetChannelFromMention(in, args[1])
		helpers.Relax(err)

		settings.PerspectiveIsParticipating = true
		settings.PerspectiveChannelID = targetChannel.ID
		*out = m.newMsg("plugins.perspective.participation-enabled")
	}

	err = helpers.GuildSettingsSet(channel.GuildID, settings)
	helpers.Relax(err)

	err = m.cacheGuildsToCheck()
	helpers.Relax(err)

	return m.actionFinish
}

func (m *Perspective) OnMessage(content string, msg *discordgo.Message, session *discordgo.Session) {
	// ignore bots
	if msg.Author.Bot {
		return
	}
	channel, err := helpers.GetChannel(msg.ChannelID)
	if err != nil {
		return
	}
	// ignore commands
	prefix := helpers.GetPrefixForServer(channel.GuildID)
	if prefix != "" {
		if strings.HasPrefix(content, prefix) {
			return
		}
	}
	// ignore music bot prefixes
	if strings.HasPrefix(content, "__") || strings.HasPrefix(content, "//") {
		return
	}
	// ignore guilds that aren't participating
	var participating bool
	for _, guildToCheck := range m.guildsToCheck {
		if guildToCheck == channel.GuildID {
			participating = true
			break
		}
	}
	if !participating {
		return
	}
	// analyze
	severeToxicity, inflammatory, obscene, err := m.analyze(msg.Content)
	helpers.Relax(err)
	// check threshold
	if severeToxicity < PerspectiveThreshold &&
		inflammatory < PerspectiveThreshold &&
		obscene < PerspectiveThreshold {
		return
	}
	// debug
	m.logger().Debugf("Severe Toxicity: %.2f, Inflammatory: %.2f, Obscene %.2f, message: %s",
		severeToxicity, inflammatory, obscene, msg.Content,
	)
	// send warning
	err = m.sendWarning(channel.GuildID, msg, severeToxicity, inflammatory, obscene)
	helpers.RelaxLog(err)
}

func (m *Perspective) sendWarning(guildID string, message *discordgo.Message, severeToxicity, inflammatory, obscene float64) (err error) {
	settings := helpers.GuildSettingsGetCached(guildID)

	if !settings.PerspectiveIsParticipating || settings.PerspectiveChannelID == "" {
		return errors.New("guild is not participating")
	}

	timestamp, err := message.Timestamp.Parse()
	if err != nil {
		timestamp = time.Now()
	}

	severeToxicityWarning := "✅ "
	inflammatoryWarning := "✅ "
	obsceneWarning := "✅ "
	if severeToxicity >= PerspectiveThreshold {
		severeToxicityWarning = "⚠ "
	}
	if inflammatory >= PerspectiveThreshold {
		inflammatoryWarning = "⚠ "
	}
	if obscene >= PerspectiveThreshold {
		obsceneWarning = "⚠ "
	}

	warningEmbed := &discordgo.MessageEmbed{
		Title:       "detected a message that possibly requires action",
		Description: message.Content,
		Timestamp:   timestamp.Format(time.RFC3339),
		Color:       helpers.GetDiscordColorFromHex("ffb80a"), // orange
		Footer: &discordgo.MessageEmbedFooter{
			Text:    helpers.GetText("plugins.perspective.embed-footer"),
			IconURL: helpers.GetText("plugins.perspective.embed-footer-imageurl"),
		},
		Author: &discordgo.MessageEmbedAuthor{
			Name:    message.Author.Username + "#" + message.Author.Discriminator + " (#" + message.Author.ID + ")",
			IconURL: message.Author.AvatarURL("64"),
		},
		Fields: []*discordgo.MessageEmbedField{
			{
				Name:   "Severe Toxicity",
				Value:  fmt.Sprintf("%s%.2f", severeToxicityWarning, severeToxicity),
				Inline: true,
			},
			{
				Name:   "Inflammatory",
				Value:  fmt.Sprintf("%s%.2f", inflammatoryWarning, inflammatory),
				Inline: true,
			},
			{
				Name:   "Obscene",
				Value:  fmt.Sprintf("%s%.2f", obsceneWarning, obscene),
				Inline: true,
			},
			{
				Name: "Channel", Value: "<#" + message.ChannelID + ">", Inline: false,
			},
		},
	}

	_, err = helpers.SendEmbed(settings.PerspectiveChannelID, warningEmbed)
	return err
}

func (m *Perspective) analyze(message string) (severeToxicity, inflammatory, obscene float64, err error) {
	// TODO: strip emoji
	requestData := &PerspectiveRequest{}
	requestData.Comment.Text = message
	requestData.Languages = []string{"en"}

	marshalled, err := json.Marshal(requestData)
	if err != nil {
		return 0, 0, 0, err
	}

	resultData, err := helpers.NetPostUAWithError(
		"https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze?key="+m.googleApiKey,
		string(marshalled),
		helpers.DEFAULT_UA,
	)
	metrics.PerspectiveApiRequests.Add(1)
	if err != nil {
		return 0, 0, 0, err
	}

	var response PerspectiveResponse
	err = json.Unmarshal(resultData, &response)
	if err != nil {
		return 0, 0, 0, err
	}

	return response.AttributeScores.SevereToxicity.SummaryScore.Value,
		response.AttributeScores.Inflammatory.SummaryScore.Value,
		response.AttributeScores.Obscene.SummaryScore.Value,
		nil
}

func (m *Perspective) cacheGuildsToCheck() (err error) {
	newGuildsToCheck := make([]string, 0)
	for _, guild := range cache.GetSession().State.Guilds {
		settings := helpers.GuildSettingsGetCached(guild.ID)
		if settings.PerspectiveIsParticipating {
			newGuildsToCheck = append(newGuildsToCheck, guild.ID)
		}
	}

	m.guildsToCheck = newGuildsToCheck

	return nil
}

func (m *Perspective) actionFinish(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	_, err := helpers.SendComplex(in.ChannelID, *out)
	helpers.Relax(err)

	return nil
}

func (m *Perspective) OnMessageDelete(msg *discordgo.MessageDelete, session *discordgo.Session) {

}

func (m *Perspective) OnGuildMemberAdd(member *discordgo.Member, session *discordgo.Session) {

}

func (m *Perspective) OnGuildMemberRemove(member *discordgo.Member, session *discordgo.Session) {

}

func (m *Perspective) OnReactionAdd(reaction *discordgo.MessageReactionAdd, session *discordgo.Session) {

}

func (m *Perspective) OnReactionRemove(reaction *discordgo.MessageReactionRemove, session *discordgo.Session) {

}

func (m *Perspective) OnGuildBanAdd(user *discordgo.GuildBanAdd, session *discordgo.Session) {

}

func (m *Perspective) OnGuildBanRemove(user *discordgo.GuildBanRemove, session *discordgo.Session) {

}

func (m *Perspective) newMsg(content string) *discordgo.MessageSend {
	return &discordgo.MessageSend{Content: helpers.GetText(content)}
}

func (m *Perspective) Relax(err error) {
	if err != nil {
		panic(err)
	}
}

func (m *Perspective) logger() *logrus.Entry {
	return cache.GetLogger().WithField("module", "perspective")
}

type PerspectiveRequest struct {
	Comment struct {
		Text string `json:"text"`
	} `json:"comment"`
	Languages           []string `json:"languages"`
	RequestedAttributes struct {
		SevereToxicity struct{} `json:"SEVERE_TOXICITY"`
		Inflammatory   struct{} `json:"INFLAMMATORY"`
		Obscene        struct{} `json:"OBSCENE"`
	} `json:"requestedAttributes"`
}

type PerspectiveResponse struct {
	AttributeScores struct {
		SevereToxicity struct {
			SummaryScore struct {
				Value float64 `json:"value"`
				Type  string  `json:"type"`
			} `json:"summaryScore"`
		} `json:"SEVERE_TOXICITY"`
		Inflammatory struct {
			SummaryScore struct {
				Value float64 `json:"value"`
				Type  string  `json:"type"`
			} `json:"summaryScore"`
		} `json:"INFLAMMATORY"`
		Obscene struct {
			SummaryScore struct {
				Value float64 `json:"value"`
				Type  string  `json:"type"`
			} `json:"summaryScore"`
		} `json:"OBSCENE"`
	} `json:"attributeScores"`
}
<commit_msg>[perspective] removes obscenity value<commit_after>package plugins

import (
	"strings"

	"encoding/json"

	"fmt"

	"time"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Seklfreak/Robyul2/metrics"
	"github.com/bwmarrin/discordgo"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

type perspectiveAction func(args []string, in *discordgo.Message, out **discordgo.MessageSend) (next perspectiveAction)

type Perspective struct {
	googleApiKey  string
	guildsToCheck []string
}

const (
	PerspectiveThreshold = 0.75
)

func (m *Perspective) Commands() []string {
	return []string{
		"perspective",
	}
}

func (m *Perspective) Init(session *discordgo.Session) {
	m.googleApiKey = helpers.GetConfig().Path("google.api_key").Data().(string)
	go func() {
		defer helpers.Recover()

		time.Sleep(60 * time.Second)
		err := m.cacheGuildsToCheck()
		helpers.Relax(err)
		m.logger().Info("initialised guilds to check cache")
	}()
}

func (m *Perspective) Uninit(session *discordgo.Session) {

}

func (m *Perspective) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	defer helpers.Recover()

	session.ChannelTyping(msg.ChannelID)

	var result *discordgo.MessageSend
	args := strings.Fields(content)

	action := m.actionStart
	for action != nil {
		action = action(args, msg, &result)
	}
}

func (m *Perspective) actionStart(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	cache.GetSession().ChannelTyping(in.ChannelID)

	if len(args) < 1 {
		*out = m.newMsg("bot.arguments.too-few")
		return m.actionFinish
	}

	switch args[0] {
	case "participate":
		return m.actionParticipate
	}

	return m.actionTest
}

// [p]perspective <message>
func (m *Perspective) actionTest(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	message := strings.TrimSpace(strings.Replace(in.Content, strings.Split(in.Content, " ")[0], "", 1))

	start := time.Now()
	severeToxicity, inflammatory, err := m.analyze(message)
	helpers.Relax(err)
	took := time.Since(start)

	var severeToxicityWarning, inflammatoryWarning string
	if severeToxicity >= PerspectiveThreshold {
		severeToxicityWarning = " ⚠"
	}
	if inflammatory >= PerspectiveThreshold {
		inflammatoryWarning = " ⚠"
	}

	*out = m.newMsg(fmt.Sprintf(
		"Severe Toxicity: %.2f%s, Inflammatory: %.2f%s\nTook %s",
		severeToxicity, severeToxicityWarning,
		inflammatory, inflammatoryWarning,
		took.String(),
	))
	return m.actionFinish
}

// [p]perspective participate [<#channel or channel id>]
func (m *Perspective) actionParticipate(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	if !helpers.IsRobyulMod(in.Author.ID) {
		*out = m.newMsg("robyulmod.no_permission")
		return m.actionFinish
	}
	if !helpers.IsAdmin(in) {
		*out = m.newMsg("admin.no_permission")
		return m.actionFinish
	}

	channel, err := helpers.GetChannel(in.ChannelID)
	helpers.Relax(err)

	settings := helpers.GuildSettingsGetCached(channel.GuildID)

	if settings.PerspectiveIsParticipating && len(args) < 2 {
		// disable perspective checking
		settings.PerspectiveIsParticipating = false
		settings.PerspectiveChannelID = ""
		*out = m.newMsg("plugins.perspective.participation-disabled")
	} else {
		// enable perspective checking
		if len(args) < 2 {
			*out = m.newMsg("bot.arguments.too-few")
			return m.actionFinish
		}

		targetChannel, err := helpers.GetChannelFromMention(in, args[1])
		helpers.Relax(err)

		settings.PerspectiveIsParticipating = true
		settings.PerspectiveChannelID = targetChannel.ID
		*out = m.newMsg("plugins.perspective.participation-enabled")
	}

	err = helpers.GuildSettingsSet(channel.GuildID, settings)
	helpers.Relax(err)

	err = m.cacheGuildsToCheck()
	helpers.Relax(err)

	return m.actionFinish
}

func (m *Perspective) OnMessage(content string, msg *discordgo.Message, session *discordgo.Session) {
	// ignore bots
	if msg.Author.Bot {
		return
	}
	channel, err := helpers.GetChannel(msg.ChannelID)
	if err != nil {
		return
	}
	// ignore commands
	prefix := helpers.GetPrefixForServer(channel.GuildID)
	if prefix != "" {
		if strings.HasPrefix(content, prefix) {
			return
		}
	}
	// ignore music bot prefixes
	if strings.HasPrefix(content, "__") || strings.HasPrefix(content, "//") {
		return
	}
	// ignore guilds that aren't participating
	var participating bool
	for _, guildToCheck := range m.guildsToCheck {
		if guildToCheck == channel.GuildID {
			participating = true
			break
		}
	}
	if !participating {
		return
	}
	// analyze
	severeToxicity, inflammatory, err := m.analyze(msg.Content)
	helpers.Relax(err)
	// check threshold
	if severeToxicity < PerspectiveThreshold &&
		inflammatory < PerspectiveThreshold {
		return
	}
	// debug
	//m.logger().Debugf("Severe Toxicity: %.2f, Inflammatory: %.2f, message: %s",
	//	severeToxicity, inflammatory, msg.Content,
	//)
	// send warning
	err = m.sendWarning(channel.GuildID, msg, severeToxicity, inflammatory)
	helpers.RelaxLog(err)
}

func (m *Perspective) sendWarning(guildID string, message *discordgo.Message, severeToxicity, inflammatory float64) (err error) {
	settings := helpers.GuildSettingsGetCached(guildID)

	if !settings.PerspectiveIsParticipating || settings.PerspectiveChannelID == "" {
		return errors.New("guild is not participating")
	}

	timestamp, err := message.Timestamp.Parse()
	if err != nil {
		timestamp = time.Now()
	}

	severeToxicityWarning := "✅ "
	inflammatoryWarning := "✅ "
	if severeToxicity >= PerspectiveThreshold {
		severeToxicityWarning = "⚠ "
	}
	if inflammatory >= PerspectiveThreshold {
		inflammatoryWarning = "⚠ "
	}

	warningEmbed := &discordgo.MessageEmbed{
		Title:       "detected a message that possibly requires action",
		Description: message.Content,
		Timestamp:   timestamp.Format(time.RFC3339),
		Color:       helpers.GetDiscordColorFromHex("ffb80a"), // orange
		Footer: &discordgo.MessageEmbedFooter{
			Text:    helpers.GetText("plugins.perspective.embed-footer"),
			IconURL: helpers.GetText("plugins.perspective.embed-footer-imageurl"),
		},
		Author: &discordgo.MessageEmbedAuthor{
			Name:    message.Author.Username + "#" + message.Author.Discriminator + " (#" + message.Author.ID + ")",
			IconURL: message.Author.AvatarURL("64"),
		},
		Fields: []*discordgo.MessageEmbedField{
			{
				Name:   "Severe Toxicity",
				Value:  fmt.Sprintf("%s%.2f", severeToxicityWarning, severeToxicity),
				Inline: true,
			},
			{
				Name:   "Inflammatory",
				Value:  fmt.Sprintf("%s%.2f", inflammatoryWarning, inflammatory),
				Inline: true,
			},
			{
				Name: "Channel", Value: "<#" + message.ChannelID + ">", Inline: false,
			},
		},
	}

	_, err = helpers.SendEmbed(settings.PerspectiveChannelID, warningEmbed)
	return err
}

func (m *Perspective) analyze(message string) (severeToxicity, inflammatory float64, err error) {
	// TODO: strip emoji
	requestData := &PerspectiveRequest{}
	requestData.Comment.Text = message
	requestData.Languages = []string{"en"}

	marshalled, err := json.Marshal(requestData)
	if err != nil {
		return 0, 0, err
	}

	resultData, err := helpers.NetPostUAWithError(
		"https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze?key="+m.googleApiKey,
		string(marshalled),
		helpers.DEFAULT_UA,
	)
	metrics.PerspectiveApiRequests.Add(1)
	if err != nil {
		return 0, 0, err
	}

	var response PerspectiveResponse
	err = json.Unmarshal(resultData, &response)
	if err != nil {
		return 0, 0, err
	}

	return response.AttributeScores.SevereToxicity.SummaryScore.Value,
		response.AttributeScores.Inflammatory.SummaryScore.Value,
		nil
}

func (m *Perspective) cacheGuildsToCheck() (err error) {
	newGuildsToCheck := make([]string, 0)
	for _, guild := range cache.GetSession().State.Guilds {
		settings := helpers.GuildSettingsGetCached(guild.ID)
		if settings.PerspectiveIsParticipating {
			newGuildsToCheck = append(newGuildsToCheck, guild.ID)
		}
	}

	m.guildsToCheck = newGuildsToCheck

	return nil
}

func (m *Perspective) actionFinish(args []string, in *discordgo.Message, out **discordgo.MessageSend) perspectiveAction {
	_, err := helpers.SendComplex(in.ChannelID, *out)
	helpers.Relax(err)

	return nil
}

func (m *Perspective) OnMessageDelete(msg *discordgo.MessageDelete, session *discordgo.Session) {

}

func (m *Perspective) OnGuildMemberAdd(member *discordgo.Member, session *discordgo.Session) {

}

func (m *Perspective) OnGuildMemberRemove(member *discordgo.Member, session *discordgo.Session) {

}

func (m *Perspective) OnReactionAdd(reaction *discordgo.MessageReactionAdd, session *discordgo.Session) {

}

func (m *Perspective) OnReactionRemove(reaction *discordgo.MessageReactionRemove, session *discordgo.Session) {

}

func (m *Perspective) OnGuildBanAdd(user *discordgo.GuildBanAdd, session *discordgo.Session) {

}

func (m *Perspective) OnGuildBanRemove(user *discordgo.GuildBanRemove, session *discordgo.Session) {

}

func (m *Perspective) newMsg(content string) *discordgo.MessageSend {
	return &discordgo.MessageSend{Content: helpers.GetText(content)}
}

func (m *Perspective) Relax(err error) {
	if err != nil {
		panic(err)
	}
}

func (m *Perspective) logger() *logrus.Entry {
	return cache.GetLogger().WithField("module", "perspective")
}

type PerspectiveRequest struct {
	Comment struct {
		Text string `json:"text"`
	} `json:"comment"`
	Languages           []string `json:"languages"`
	RequestedAttributes struct {
		SevereToxicity struct{} `json:"SEVERE_TOXICITY"`
		Inflammatory   struct{} `json:"INFLAMMATORY"`
	} `json:"requestedAttributes"`
}

type PerspectiveResponse struct {
	AttributeScores struct {
		SevereToxicity struct {
			SummaryScore struct {
				Value float64 `json:"value"`
				Type  string  `json:"type"`
			} `json:"summaryScore"`
		} `json:"SEVERE_TOXICITY"`
		Inflammatory struct {
			SummaryScore struct {
				Value float64 `json:"value"`
				Type  string  `json:"type"`
			} `json:"summaryScore"`
		} `json:"INFLAMMATORY"`
	} `json:"attributeScores"`
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
)

func appDirExists(application *Application, etcd *Etcd) bool {
	return etcd.HasKey("/paus/users/" + application.Username + "/apps/" + application.AppName)
}

func deploy(dockerHost string, application *Application, composeFilePath string) (string, error) {
	var err error

	compose := NewCompose(dockerHost, composeFilePath, application.ProjectName)

	fmt.Println("=====> Building ...")

	if err = compose.Build(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to build application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Pulling ...")

	if err = compose.Pull(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to pull application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Deploying ...")

	if err = compose.Up(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to start application. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	webContainerId, err := compose.GetContainerId("web")

	if err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to web container ID. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	return webContainerId, nil
}

func getSubmodules(repositoryPath string) error {
	dir := filepath.Join(repositoryPath, ".git")

	stat, err := os.Stat(dir)

	if err == nil && stat.IsDir() {
		if e := os.RemoveAll(dir); e != nil {
			return errors.Wrap(e, fmt.Sprintf("Failed to remove %s.", dir))
		}
	}

	cmd := exec.Command("/usr/local/bin/get-submodules")

	if err = RunCommand(cmd); err != nil {
		return errors.Wrap(err, "Failed to get submodules.")
	}

	return nil
}

func injectBuildArgs(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	buildArgsKey := appDirectoryKey + "/build-args/"

	if !etcd.HasKey(buildArgsKey) {
		return nil
	}

	buildArgKeys, err := etcd.List(buildArgsKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get build arg keys.")
	}

	buildArgs := map[string]string{}

	for _, key := range buildArgKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get build arg value. key: %s", key))
		}

		buildArgs[strings.Replace(key, buildArgsKey, "", 1)] = value
	}

	composeFile.InjectBuildArgs(buildArgs)

	return nil
}

func injectEnvironmentVariables(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	envDirectoryKey := appDirectoryKey + "/envs/"

	if !etcd.HasKey(envDirectoryKey) {
		return nil
	}

	envKeys, err := etcd.List(envDirectoryKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get environment variable keys.")
	}

	environmentVariables := map[string]string{}

	for _, key := range envKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get environment variable value. key: %s", key))
		}

		environmentVariables[strings.Replace(key, envDirectoryKey, "", 1)] = value
	}

	composeFile.InjectEnvironmentVariables(environmentVariables)

	return nil
}

func registerApplicationMetadata(application *Application, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		_ = etcd.Mkdir(userDirectoryKey)
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		_ = etcd.Mkdir(appDirectoryKey)
		_ = etcd.Mkdir(appDirectoryKey + "/envs")
		_ = etcd.Mkdir(appDirectoryKey + "/revisions")
	}

	if err := etcd.Set(appDirectoryKey+"/revisions/"+application.Revision, strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
		return errors.Wrap(err, "Failed to set revisdion.")
	}

	return nil
}

func registerVulcandInformation(application *Application, baseDomain string, webContainer *Container, etcd *Etcd) error {
	vulcand := NewVulcand(etcd)

	if err := vulcand.SetBackend(application, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	for _, identifier := range []string{application.ProjectName, fmt.Sprintf("%s-%s", application.Username, application.AppName)} {
		if err := vulcand.SetFrontend(application, identifier, baseDomain); err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to set vulcand frontend. identifier: %s", identifier))
		}
	}

	if err := vulcand.SetServer(application, webContainer, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	return nil
}

func removeUnpackedFiles(repositoryPath, newComposeFilePath string) error {
	files, err := ioutil.ReadDir(repositoryPath)

	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("Failed to open %s.", repositoryPath))
	}

	for _, file := range files {
		if filepath.Join(repositoryPath, file.Name()) != newComposeFilePath {
			path := filepath.Join(repositoryPath, file.Name())

			if err = os.RemoveAll(path); err != nil {
				return errors.Wrap(err, fmt.Sprintf("Failed to remove files in %s.", path))
			}
		}
	}

	return nil
}

func unpackReceivedFiles(repositoryDir, username, projectName string, stdin io.Reader) (string, error) {
	repositoryPath := filepath.Join(repositoryDir, username, projectName)

	if err := os.MkdirAll(repositoryPath, 0777); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s.", repositoryPath))
	}

	reader := tar.NewReader(stdin)

	for {
		header, err := reader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return "", errors.Wrap(err, "Failed to iterate tarball.")
		}

		buffer := new(bytes.Buffer)
		outPath := filepath.Join(repositoryPath, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if _, err = os.Stat(outPath); err != nil {
				if err = os.MkdirAll(outPath, 0755); err != nil {
					return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s from tarball.", outPath))
				}
			}

		case tar.TypeReg, tar.TypeRegA:
			if _, err = io.Copy(buffer, reader); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to copy file contents in %s from tarball.", outPath))
			}

			if err = ioutil.WriteFile(outPath, buffer.Bytes(), os.FileMode(header.Mode)); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to create file %s from tarball.", outPath))
			}
		}
	}

	return repositoryPath, nil
}

func main() {
	config, err := LoadConfig()

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	etcd, err := NewEtcd(config.EtcdEndpoint)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	application := ApplicationFromArgs(os.Args[1:])

	if !appDirExists(application, etcd) {
		fmt.Fprintln(os.Stderr, "=====> Application not found: "+application.AppName)
		os.Exit(1)
	}

	repositoryPath, err := unpackReceivedFiles(config.RepositoryDir, application.Username, application.ProjectName, os.Stdin)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = os.Chdir(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to chdir to %s.", repositoryPath)))
		os.Exit(1)
	}

	fmt.Println("=====> Getting submodules ...")

	if err = getSubmodules(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to get submodules. path: %s", repositoryPath)))
		os.Exit(1)
	}

	composeFilePath := filepath.Join(repositoryPath, "docker-compose.yml")

	if _, err := os.Stat(composeFilePath); err != nil {
		fmt.Fprintln(os.Stderr, "=====> docker-compose.yml was NOT found!")
		os.Exit(1)
	}

	fmt.Println("=====> docker-compose.yml was found")
	composeFile, err := NewComposeFile(composeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectBuildArgs(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectEnvironmentVariables(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	composeFile.RewritePortBindings()
	newComposeFilePath := filepath.Join(repositoryPath, "docker-compose-"+strconv.FormatInt(time.Now().Unix(), 10)+".yml")

	if err = composeFile.SaveAs(newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	webContainerId, err := deploy(config.DockerHost, application, newComposeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Application container is launched.")

	webContainer, err := ContainerFromID(config.DockerHost, webContainerId)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Registering metadata ...")

	if err = registerApplicationMetadata(application, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = registerVulcandInformation(application, config.BaseDomain, webContainer, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	uriScheme, err := etcd.Get("/paus/uri-scheme")

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	urlList := []string{
		uriScheme + "://" + application.ProjectName + "." + config.BaseDomain,
		uriScheme + "://" + application.Username + "." + application.AppName + "." + config.BaseDomain,
	}

	fmt.Println("=====> " + application.Repository + " was successfully deployed at:")

	for _, url := range urlList {
		fmt.Println("         " + url)
	}

	if err = removeUnpackedFiles(repositoryPath, newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Modify URL shown in stdout<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
)

func appDirExists(application *Application, etcd *Etcd) bool {
	return etcd.HasKey("/paus/users/" + application.Username + "/apps/" + application.AppName)
}

func deploy(dockerHost string, application *Application, composeFilePath string) (string, error) {
	var err error

	compose := NewCompose(dockerHost, composeFilePath, application.ProjectName)

	fmt.Println("=====> Building ...")

	if err = compose.Build(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to build application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Pulling ...")

	if err = compose.Pull(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to pull application image. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	fmt.Println("=====> Deploying ...")

	if err = compose.Up(); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to start application. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	webContainerId, err := compose.GetContainerId("web")

	if err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to web container ID. appName: %s, composeFilePath: %s", application.AppName, composeFilePath))
	}

	return webContainerId, nil
}

func getSubmodules(repositoryPath string) error {
	dir := filepath.Join(repositoryPath, ".git")

	stat, err := os.Stat(dir)

	if err == nil && stat.IsDir() {
		if e := os.RemoveAll(dir); e != nil {
			return errors.Wrap(e, fmt.Sprintf("Failed to remove %s.", dir))
		}
	}

	cmd := exec.Command("/usr/local/bin/get-submodules")

	if err = RunCommand(cmd); err != nil {
		return errors.Wrap(err, "Failed to get submodules.")
	}

	return nil
}

func injectBuildArgs(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	buildArgsKey := appDirectoryKey + "/build-args/"

	if !etcd.HasKey(buildArgsKey) {
		return nil
	}

	buildArgKeys, err := etcd.List(buildArgsKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get build arg keys.")
	}

	buildArgs := map[string]string{}

	for _, key := range buildArgKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get build arg value. key: %s", key))
		}

		buildArgs[strings.Replace(key, buildArgsKey, "", 1)] = value
	}

	composeFile.InjectBuildArgs(buildArgs)

	return nil
}

func injectEnvironmentVariables(application *Application, composeFile *ComposeFile, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		return nil
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		return nil
	}

	envDirectoryKey := appDirectoryKey + "/envs/"

	if !etcd.HasKey(envDirectoryKey) {
		return nil
	}

	envKeys, err := etcd.List(envDirectoryKey, false)

	if err != nil {
		return errors.Wrap(err, "Failed to get environment variable keys.")
	}

	environmentVariables := map[string]string{}

	for _, key := range envKeys {
		value, err := etcd.Get(key)

		if err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to get environment variable value. key: %s", key))
		}

		environmentVariables[strings.Replace(key, envDirectoryKey, "", 1)] = value
	}

	composeFile.InjectEnvironmentVariables(environmentVariables)

	return nil
}

func registerApplicationMetadata(application *Application, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + application.Username

	if !etcd.HasKey(userDirectoryKey) {
		_ = etcd.Mkdir(userDirectoryKey)
	}

	appDirectoryKey := userDirectoryKey + "/apps/" + application.AppName

	if !etcd.HasKey(appDirectoryKey) {
		_ = etcd.Mkdir(appDirectoryKey)
		_ = etcd.Mkdir(appDirectoryKey + "/envs")
		_ = etcd.Mkdir(appDirectoryKey + "/revisions")
	}

	if err := etcd.Set(appDirectoryKey+"/revisions/"+application.Revision, strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
		return errors.Wrap(err, "Failed to set revisdion.")
	}

	return nil
}

func registerVulcandInformation(application *Application, baseDomain string, webContainer *Container, etcd *Etcd) error {
	vulcand := NewVulcand(etcd)

	if err := vulcand.SetBackend(application, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	for _, identifier := range []string{application.ProjectName, fmt.Sprintf("%s-%s", application.Username, application.AppName)} {
		if err := vulcand.SetFrontend(application, identifier, baseDomain); err != nil {
			return errors.Wrap(err, fmt.Sprintf("Failed to set vulcand frontend. identifier: %s", identifier))
		}
	}

	if err := vulcand.SetServer(application, webContainer, baseDomain); err != nil {
		return errors.Wrap(err, "Failed to set vulcand backend.")
	}

	return nil
}

func removeUnpackedFiles(repositoryPath, newComposeFilePath string) error {
	files, err := ioutil.ReadDir(repositoryPath)

	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("Failed to open %s.", repositoryPath))
	}

	for _, file := range files {
		if filepath.Join(repositoryPath, file.Name()) != newComposeFilePath {
			path := filepath.Join(repositoryPath, file.Name())

			if err = os.RemoveAll(path); err != nil {
				return errors.Wrap(err, fmt.Sprintf("Failed to remove files in %s.", path))
			}
		}
	}

	return nil
}

func unpackReceivedFiles(repositoryDir, username, projectName string, stdin io.Reader) (string, error) {
	repositoryPath := filepath.Join(repositoryDir, username, projectName)

	if err := os.MkdirAll(repositoryPath, 0777); err != nil {
		return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s.", repositoryPath))
	}

	reader := tar.NewReader(stdin)

	for {
		header, err := reader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return "", errors.Wrap(err, "Failed to iterate tarball.")
		}

		buffer := new(bytes.Buffer)
		outPath := filepath.Join(repositoryPath, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if _, err = os.Stat(outPath); err != nil {
				if err = os.MkdirAll(outPath, 0755); err != nil {
					return "", errors.Wrap(err, fmt.Sprintf("Failed to create directory %s from tarball.", outPath))
				}
			}

		case tar.TypeReg, tar.TypeRegA:
			if _, err = io.Copy(buffer, reader); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to copy file contents in %s from tarball.", outPath))
			}

			if err = ioutil.WriteFile(outPath, buffer.Bytes(), os.FileMode(header.Mode)); err != nil {
				return "", errors.Wrap(err, fmt.Sprintf("Failed to create file %s from tarball.", outPath))
			}
		}
	}

	return repositoryPath, nil
}

func main() {
	config, err := LoadConfig()

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	etcd, err := NewEtcd(config.EtcdEndpoint)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	application := ApplicationFromArgs(os.Args[1:])

	if !appDirExists(application, etcd) {
		fmt.Fprintln(os.Stderr, "=====> Application not found: "+application.AppName)
		os.Exit(1)
	}

	repositoryPath, err := unpackReceivedFiles(config.RepositoryDir, application.Username, application.ProjectName, os.Stdin)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = os.Chdir(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to chdir to %s.", repositoryPath)))
		os.Exit(1)
	}

	fmt.Println("=====> Getting submodules ...")

	if err = getSubmodules(repositoryPath); err != nil {
		errors.Fprint(os.Stderr, errors.Wrap(err, fmt.Sprintf("Failed to get submodules. path: %s", repositoryPath)))
		os.Exit(1)
	}

	composeFilePath := filepath.Join(repositoryPath, "docker-compose.yml")

	if _, err := os.Stat(composeFilePath); err != nil {
		fmt.Fprintln(os.Stderr, "=====> docker-compose.yml was NOT found!")
		os.Exit(1)
	}

	fmt.Println("=====> docker-compose.yml was found")
	composeFile, err := NewComposeFile(composeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectBuildArgs(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = injectEnvironmentVariables(application, composeFile, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	composeFile.RewritePortBindings()
	newComposeFilePath := filepath.Join(repositoryPath, "docker-compose-"+strconv.FormatInt(time.Now().Unix(), 10)+".yml")

	if err = composeFile.SaveAs(newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	webContainerId, err := deploy(config.DockerHost, application, newComposeFilePath)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Application container is launched.")

	webContainer, err := ContainerFromID(config.DockerHost, webContainerId)

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Registering metadata ...")

	if err = registerApplicationMetadata(application, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	if err = registerVulcandInformation(application, config.BaseDomain, webContainer, etcd); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	uriScheme, err := etcd.Get("/paus/uri-scheme")

	if err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}

	urlList := []string{
		uriScheme + "://" + application.ProjectName + "." + config.BaseDomain,
		uriScheme + "://" + application.Username + "-" + application.AppName + "." + config.BaseDomain,
	}

	fmt.Println("=====> " + application.Repository + " was successfully deployed at:")

	for _, url := range urlList {
		fmt.Println("         " + url)
	}

	if err = removeUnpackedFiles(repositoryPath, newComposeFilePath); err != nil {
		errors.Fprint(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package tabio

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strings"
)

type RecordReader struct {
	reader io.ReadCloser
	runeReader io.RuneReader

	buffer bytes.Buffer
	err error

	cachedColumns []string

}

func NewRecordReader(r io.ReadCloser) *RecordReader {
	runeReader, ok := r.(io.RuneReader)
	if !ok {
		runeReader = bufio.NewReader(r)
	}

	rr := RecordReader{
		reader:     r,
		runeReader: runeReader,
	}

	if !rr.Next() {
		return &rr
	}

	cachedColumns, err := rr.Fields()
	if nil != err {
		rr.err = err
		return &rr
	}

	rr.cachedColumns = cachedColumns

	return &rr
}

func (rr *RecordReader) Close() error {
	return rr.reader.Close()
}

func (rr *RecordReader) Columns() ([]string, error) {
	if nil == rr {
		return nil, errNilReceiver
	}

	cachedColumns := rr.cachedColumns
	if nil == cachedColumns {
		return []string{}, nil
	}

//@TODO: Should we return a copy of this instead?
	return cachedColumns, nil
}

func (rr *RecordReader) MustColumns() []string {
	cols, err := rr.Columns()
	if nil != err {
		panic(err)
	}

	return cols
}

func (rr *RecordReader) Err() error {
	return rr.err
}

func (rr *RecordReader) Fields() ([]string, error) {
	const US = "\x1f" // Unit Separator

	if nil == rr {
		return nil, errInternalError
	}

	return strings.Split(rr.buffer.String(), US), nil
}

func (rr *RecordReader) MustFields() []string {
	fields, err := rr.Fields()
	if nil != err {
		panic(err)
	}

	return fields
}

func (rr *RecordReader) Next() bool {

	const RS rune = 30 // Record Separator

	if nil == rr {
		panic(errNilReceiver)
	}

	runeReader := rr.runeReader
	if nil == runeReader {
		panic(errInternalError)
	}

	rr.buffer.Reset()

	var r rune
	var err error
	for {
		r, _, err = runeReader.ReadRune()
		if io.EOF == err {
			return 0 < rr.buffer.Len()
		}
		if nil != err {
			rr.err = err
			return false
		}

		if RS == r {
			return true
		}

		rr.buffer.WriteRune(r)
	}
}

func (rr *RecordReader) Scan(dest ...interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	lenColumns := 0
	if cachedColumns := rr.cachedColumns; nil != cachedColumns {
		lenColumns = len(cachedColumns)
	}

	if lenDest := len(dest); lenColumns != lenDest {
		return internalWrongNumberOfArgumentsComplainer{expected: uint(lenColumns), actual: uint(lenDest) }
	}

//@TODO: Do this better.
	fields, err := rr.Fields()
	if nil != err {
		return err
	}
	for i, _ := range dest {
//@TODO: need to handle converions... probably.
		switch dest[i].(type) {
		case *string:
			dest[i] = &fields[i]
		default:
			return internalUnsupportedScanComplainer{
				srcType:  fmt.Sprintf("%T", &fields[i]),
				destType: fmt.Sprintf("%T", dest[i]),
			}
		}
	}

	return nil
}

func (rr *RecordReader) MustScan(dest ...interface{}) {
	if err := rr.Scan(dest...); nil != err {
		panic(err)
	}
}

func (rr *RecordReader) Unmarshal(target interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	switch x:= target.(type) {
	case RecordUnmarshaler:
		bs := rr.buffer.Bytes()

		if err := x.UnmarshalRecord(bs); nil != err {
			return err
		}
	default:
panic("//@TODO TODO TODO TODO TODO")

	}

	return nil
}

func (rr *RecordReader) MustUnmarshal(target interface{}) {
	if err := rr.Unmarshal(target); nil != err {
		panic(err)
	}
}
<commit_msg>improved *RecordReader.Close<commit_after>package tabio

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strings"
)

type RecordReader struct {
	reader io.ReadCloser
	runeReader io.RuneReader

	buffer bytes.Buffer
	err error

	cachedColumns []string

	closed bool
}

func NewRecordReader(r io.ReadCloser) *RecordReader {
	runeReader, ok := r.(io.RuneReader)
	if !ok {
		runeReader = bufio.NewReader(r)
	}

	rr := RecordReader{
		reader:     r,
		runeReader: runeReader,
	}

	if !rr.Next() {
		return &rr
	}

	cachedColumns, err := rr.Fields()
	if nil != err {
		rr.err = err
		return &rr
	}

	rr.cachedColumns = cachedColumns

	return &rr
}

// Close closes the *RecordReader, preventing further iterator.
//
// If Next returns false then the *RecordReader is closed automatically.
//
// Close is idempotent and does not affect the result of Err.
//
// The first time Close is called it will in turn call Close on the wrapped io.ReadCloser that way passed to NewRecordReader.
func (rr *RecordReader) Close() error {
	if rr.closed {
		return nil
	}

	return rr.reader.Close()
}

func (rr *RecordReader) Columns() ([]string, error) {
	if nil == rr {
		return nil, errNilReceiver
	}

	cachedColumns := rr.cachedColumns
	if nil == cachedColumns {
		return []string{}, nil
	}

//@TODO: Should we return a copy of this instead?
	return cachedColumns, nil
}

func (rr *RecordReader) MustColumns() []string {
	cols, err := rr.Columns()
	if nil != err {
		panic(err)
	}

	return cols
}

func (rr *RecordReader) Err() error {
	return rr.err
}

func (rr *RecordReader) Fields() ([]string, error) {
	const US = "\x1f" // Unit Separator

	if nil == rr {
		return nil, errInternalError
	}

	return strings.Split(rr.buffer.String(), US), nil
}

func (rr *RecordReader) MustFields() []string {
	fields, err := rr.Fields()
	if nil != err {
		panic(err)
	}

	return fields
}

func (rr *RecordReader) Next() bool {

	const RS rune = 30 // Record Separator

	if nil == rr {
		panic(errNilReceiver)
	}

	if rr.closed {
		return false
	}

	runeReader := rr.runeReader
	if nil == runeReader {
		panic(errInternalError)
	}

	rr.buffer.Reset()

	var r rune
	var err error
	for {
		r, _, err = runeReader.ReadRune()
		if io.EOF == err {
			next := 0 < rr.buffer.Len()
			if !next {
				rr.Close()
			}

			return next
		}
		if nil != err {
			rr.err = err
			rr.Close()
			return false
		}

		if RS == r {
			return true
		}

		rr.buffer.WriteRune(r)
	}
}

func (rr *RecordReader) Scan(dest ...interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	lenColumns := 0
	if cachedColumns := rr.cachedColumns; nil != cachedColumns {
		lenColumns = len(cachedColumns)
	}

	if lenDest := len(dest); lenColumns != lenDest {
		return internalWrongNumberOfArgumentsComplainer{expected: uint(lenColumns), actual: uint(lenDest) }
	}

//@TODO: Do this better.
	fields, err := rr.Fields()
	if nil != err {
		return err
	}
	for i, _ := range dest {
//@TODO: need to handle converions... probably.
		switch dest[i].(type) {
		case *string:
			dest[i] = &fields[i]
		default:
			return internalUnsupportedScanComplainer{
				srcType:  fmt.Sprintf("%T", &fields[i]),
				destType: fmt.Sprintf("%T", dest[i]),
			}
		}
	}

	return nil
}

func (rr *RecordReader) MustScan(dest ...interface{}) {
	if err := rr.Scan(dest...); nil != err {
		panic(err)
	}
}

func (rr *RecordReader) Unmarshal(target interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	switch x:= target.(type) {
	case RecordUnmarshaler:
		bs := rr.buffer.Bytes()

		if err := x.UnmarshalRecord(bs); nil != err {
			return err
		}
	default:
panic("//@TODO TODO TODO TODO TODO")

	}

	return nil
}

func (rr *RecordReader) MustUnmarshal(target interface{}) {
	if err := rr.Unmarshal(target); nil != err {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/op/go-logging"
	"os"
	"os/exec"
	"regexp"
)

var log = logging.MustGetLogger("Govis")
var format = logging.MustStringFormatter("%{color}[%{id:03x}] %{time:15:04:05} %{level:.4s}%{color:reset} %{message}")

func main() {
	backend := logging.NewLogBackend(os.Stderr, "", 0)
	backendFormatter := logging.NewBackendFormatter(backend, format)
	logging.SetBackend(backendFormatter)

	fmt.Println(GetCurrentWindowName())
}

func GetCurrentWindowID() string {
	out, err := exec.Command("xprop", "-root", "_NET_ACTIVE_WINDOW").Output()

	if err != nil {
		log.Warning("Could get current window id: %s", err)
		return ""
	}

	re := regexp.MustCompile(`0x[a-f0-9]+`)
	match := re.FindStringSubmatch(string(out))

	if len(match) < 1 {
		log.Warning("Could get current window id")
		return ""
	}

	return match[0]
}

func GetCurrentWindowName() string {
	out, err := exec.Command("xprop", "-id", GetCurrentWindowID(), "_NET_WM_NAME").Output()

	if err != nil {
		log.Warning("Could get current window name: %s", err)
		return ""
	}

	fmt.Println(string(out))

	re := regexp.MustCompile(`"(.*)"`)
	match := re.FindStringSubmatch(string(out))

	if len(match) < 2 {
		log.Warning("Could get current window name")
		return ""
	}

	return match[1]
}
<commit_msg>added time tracking and started getting settings<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/op/go-logging"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"time"
)

var log = logging.MustGetLogger("Govis")
var format = logging.MustStringFormatter("%{color}[%{id:03x}] %{time:15:04:05} %{level:.4s}%{color:reset} %{message}")

var configFileName = "govis.json"

func main() {
	backend := logging.NewLogBackend(os.Stderr, "", 0)
	backendFormatter := logging.NewBackendFormatter(backend, format)
	logging.SetBackend(backendFormatter)

	c := JsonCfg{}
	fmt.Println(c.GetConfigFile(configFileName))

	TrackTime()
}

type JsonCfg struct {
	TickInterval int
	LogName      string
}

func (I *JsonCfg) GetConfigFile(path string) *JsonCfg {
	b, err := ioutil.ReadFile(path)

	if err != nil {
		log.Error("%s", err)
	}

	err = json.Unmarshal(b, &I)

	if err != nil {
		log.Error("%s", err)
	}
	return I
}

func TrackTime() {
	lastTime := time.Now()
	lastWindow := GetCurrentWindowName()

	c := time.Tick(400 * time.Millisecond)
	for now := range c {
		currentWindow := GetCurrentWindowName()

		if currentWindow != lastWindow {
			timeDiff := time.Now().Sub(lastTime)
			fmt.Printf("Changed from %s to %s for %s", lastWindow, currentWindow, timeDiff)
		}

		lastWindow = currentWindow
		var _ = now
	}
}

func GetCurrentWindowID() string {
	out, err := exec.Command("xprop", "-root", "_NET_ACTIVE_WINDOW").Output()

	if err != nil {
		log.Warning("Could get current window id: %s", err)
		return ""
	}

	re := regexp.MustCompile(`0x[a-f0-9]+`)
	match := re.FindStringSubmatch(string(out))

	if len(match) < 1 {
		log.Warning("Could get current window id")
		return ""
	}

	return match[0]
}

func GetCurrentWindowName() string {
	out, err := exec.Command("xprop", "-id", GetCurrentWindowID(), "_NET_WM_NAME").Output()

	if err != nil {
		log.Warning("Could get current window name: %s", err)
		return ""
	}

	re := regexp.MustCompile(`"(.*)"`)
	match := re.FindStringSubmatch(string(out))

	if len(match) < 2 {
		log.Warning("Could get current window name")
		return ""
	}

	return match[1]
}
<|endoftext|>


<commit_before>package authentication

import (
	"fmt"
	"net/http"

	"github.com/SpectoLabs/hoverfly/authentication/backends"
	jwt "github.com/dgrijalva/jwt-go"
)

type AuthMiddleware struct {
	AB                 backends.AuthBackend
	SecretKey          []byte
	JWTExpirationDelta int
	Enabled            bool
}

func GetNewAuthenticationMiddleware(authBackend backends.AuthBackend, secretKey []byte, exp int, enabled bool) *AuthMiddleware {
	return &AuthMiddleware{AB: authBackend, SecretKey: secretKey, JWTExpirationDelta: exp, Enabled: enabled}
}

func (a *AuthMiddleware) RequireTokenAuthentication(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// if auth is disabled - do not check token
	if !a.Enabled {
		next(w, req)
	}

	authBackend := InitJWTAuthenticationBackend(a.AB, a.SecretKey, a.JWTExpirationDelta)

	token, err := jwt.ParseFromRequest(req, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		} else {
			return authBackend.SecretKey, nil
		}
	})

	if err == nil && token.Valid && !authBackend.IsInBlacklist(req.Header.Get("Authorization")) {
		next(w, req)
	} else {
		w.WriteHeader(http.StatusUnauthorized)
	}
}
<commit_msg>fixed small bug with multiple headers<commit_after>package authentication

import (
	"fmt"
	"net/http"

	"github.com/SpectoLabs/hoverfly/authentication/backends"
	jwt "github.com/dgrijalva/jwt-go"
)

type AuthMiddleware struct {
	AB                 backends.AuthBackend
	SecretKey          []byte
	JWTExpirationDelta int
	Enabled            bool
}

func GetNewAuthenticationMiddleware(authBackend backends.AuthBackend, secretKey []byte, exp int, enabled bool) *AuthMiddleware {
	return &AuthMiddleware{AB: authBackend, SecretKey: secretKey, JWTExpirationDelta: exp, Enabled: enabled}
}

func (a *AuthMiddleware) RequireTokenAuthentication(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	// if auth is disabled - do not check token
	if !a.Enabled {
		next(w, req)
		return
	}

	authBackend := InitJWTAuthenticationBackend(a.AB, a.SecretKey, a.JWTExpirationDelta)

	token, err := jwt.ParseFromRequest(req, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
		} else {
			return authBackend.SecretKey, nil
		}
	})

	if err == nil && token.Valid && !authBackend.IsInBlacklist(req.Header.Get("Authorization")) {
		next(w, req)
	} else {
		w.WriteHeader(http.StatusUnauthorized)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 ego authors
//
// 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 (
	"log"

	"github.com/go-ego/riot"
	"github.com/go-ego/riot/types"
)

var (
	// searcher is coroutine safe
	searcher = riot.Engine{}

	data = types.DocData{
		Content: "Google Is Experimenting With Virtual Reality Advertising",
	}

	data1 = types.DocData{
		Content: `Google accidentally pushed Bluetooth update for Home
	speaker early`,
	}

	data2 = types.DocData{
		Content: `Google is testing another Search results layout with
	rounded cards, new colors, and the 4 mysterious colored dots again`,
	}

	data3 = types.DocData{
		Content: "Google testing text search",
	}

	rankOpts = types.RankOpts{
		OutputOffset: 0,
		MaxOutputs:   100,
	}
)

func addDocs(search *riot.Engine) {
	// Add the document to the index, docId starts at 1
	search.Index(1, data)
	search.Index(2, data1)
	search.Index(3, data2)
	search.Index(4, data3)

	// Wait for the index to refresh
	search.Flush()
}

func logic1() {
	// Init engine
	searcher.Init(types.EngineOpts{
		// Using:     4,
		IDOnly:    true,
		NotUseGse: true,
	})
	defer searcher.Close()

	addDocs(&searcher)

	// var strArr []string
	strArr := []string{"accidentally"}
	// strArr := []string{"text"}
	query := "google testing"

	// Search "google testing" segmentation `or relation`
	// and not the result of "accidentally"
	logic := types.Logic{
		Should: true,
		LogicExpr: types.LogicExpr{
			NotInLabels: strArr,
		},
	}

	// The search output format is found in the types.SearchResp structure
	docs := searcher.SearchID(types.SearchReq{
		Text:     query,
		Logic:    logic,
		RankOpts: &rankOpts,
	})

	log.Println("search response: ", len(docs.Docs), docs)
}

func logic2() {
	// Init engine
	var searcher1 = riot.New()

	data4 := types.DocData{Content: "Google testing search"}

	// Add the document to the index, docId starts at 1
	addDocs(searcher1)
	searcher1.Index(5, data4)

	// Wait for the index to refresh
	searcher1.Flush()

	// var strArr []string
	strArr := []string{"accidentally"}
	notArr := []string{"text"}
	query := "google testing"

	// Search "google testing" segmentation `must relation`
	// and the result of "or accidentally"
	logic := types.Logic{
		Should: true,
		LogicExpr: types.LogicExpr{
			// ShouldLabels: strArr,
			MustLabels:  strArr,
			NotInLabels: notArr,
		},
	}

	// The search output format is found in the types.SearchResp structure
	docs := searcher1.Search(types.SearchReq{
		Text:     query,
		Logic:    logic,
		RankOpts: &rankOpts,
	})

	log.Println("search response: ", docs.NumDocs, docs)
}

func main() {
	logic1()
	logic2()
}
<commit_msg>update logic example code<commit_after>// Copyright 2016 ego authors
//
// 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 (
	"log"

	"github.com/go-ego/riot"
	"github.com/go-ego/riot/types"
)

var (
	// searcher is coroutine safe
	searcher = riot.Engine{}

	data = types.DocData{
		Content: "Google Is Experimenting With Virtual Reality Advertising",
	}

	data1 = types.DocData{
		Content: `Google accidentally pushed Bluetooth update for Home
	speaker early`,
	}

	data2 = types.DocData{
		Content: `Google is testing another Search results layout with
	rounded cards, new colors, and the 4 mysterious colored dots again`,
	}

	data3 = types.DocData{
		Content: "Google testing text search",
	}

	rankOpts = types.RankOpts{
		OutputOffset: 0,
		MaxOutputs:   100,
	}
)

func addDocs(search *riot.Engine) {
	// Add the document to the index, docId starts at 1
	search.Index("1", data)
	search.Index("2", data1)
	search.Index("3", data2)
	search.Index("4", data3)

	// Wait for the index to refresh
	search.Flush()
}

func logic1() {
	// Init engine
	searcher.Init(types.EngineOpts{
		// Using:     4,
		IDOnly:    true,
		NotUseGse: true,
	})
	defer searcher.Close()

	addDocs(&searcher)

	// var strArr []string
	strArr := []string{"accidentally"}
	// strArr := []string{"text"}
	query := "google testing"

	// Search "google testing" segmentation `or relation`
	// and not the result of "accidentally"
	logic := types.Logic{
		Should: true,
		Expr: types.Expr{
			NotIn: strArr,
		},
	}

	// The search output format is found in the types.SearchResp structure
	docs := searcher.SearchID(types.SearchReq{
		Text:     query,
		Logic:    logic,
		RankOpts: &rankOpts,
	})

	log.Println("search response: ", len(docs.Docs), docs)
}

func logic2() {
	// Init engine
	var searcher1 = riot.New()

	data4 := types.DocData{Content: "Google testing search"}

	// Add the document to the index, docId starts at 1
	addDocs(searcher1)
	searcher1.Index("5", data4)

	// Wait for the index to refresh
	searcher1.Flush()

	// var strArr []string
	strArr := []string{"accidentally"}
	notArr := []string{"text"}
	query := "google testing"

	// Search "google testing" segmentation `must relation`
	// and the result of "or accidentally"
	logic := types.Logic{
		Should: true,
		Expr: types.Expr{
			// Should: strArr,
			Must:  strArr,
			NotIn: notArr,
		},
	}

	// The search output format is found in the types.SearchResp structure
	docs := searcher1.Search(types.SearchReq{
		Text:     query,
		Logic:    logic,
		RankOpts: &rankOpts,
	})

	log.Println("search response: ", docs.NumDocs, docs)
}

func main() {
	logic1()
	logic2()
}
<|endoftext|>


<commit_before>// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package main

import (
	"fmt"

	"github.com/go-vgo/robotgo"
	// "go-vgo/robotgo"
)

func move() {
	robotgo.Move(100, 200)

	// move the mouse to 100, 200
	robotgo.MoveMouse(100, 200)

	// smooth move the mouse to 100, 200
	robotgo.MoveSmooth(100, 200)
	robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0)

	for i := 0; i < 1080; i += 1000 {
		fmt.Println(i)
		robotgo.MoveMouse(800, i)
	}
}

func click() {

	// click the left mouse button
	robotgo.Click()
	// click the right mouse button
	robotgo.Click("right", false)
	// double click the left mouse button
	robotgo.MouseClick("left", true)
}

func get() {
	// gets the mouse coordinates
	x, y := robotgo.GetMousePos()
	fmt.Println("pos:", x, y)
	if x == 456 && y == 586 {
		fmt.Println("mouse...", "586")
	}

	robotgo.MoveMouse(x, y)
}

func toggleAndScroll() {
	// scrolls the mouse either up
	robotgo.ScrollMouse(10, "up")
	robotgo.Scroll(100, 200)

	// toggles right mouse button
	robotgo.MouseToggle("down", "right")

	robotgo.MouseToggle("up")
}

func mouse() {
	////////////////////////////////////////////////////////////////////////////////
	// Control the mouse
	////////////////////////////////////////////////////////////////////////////////

	move()

	click()

	get()

	toggleAndScroll()
}

func main() {
	mouse()
}
<commit_msg>add more mouse example<commit_after>// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package main

import (
	"fmt"

	"github.com/go-vgo/robotgo"
	// "go-vgo/robotgo"
)

func move() {
	robotgo.Move(100, 200)

	// move the mouse to 100, 200
	robotgo.MoveMouse(100, 200)

	robotgo.Drag(10, 10)
	robotgo.Drag(20, 20, "right")

	// smooth move the mouse to 100, 200
	robotgo.MoveSmooth(100, 200)
	robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0)

	for i := 0; i < 1080; i += 1000 {
		fmt.Println(i)
		robotgo.MoveMouse(800, i)
	}
}

func click() {

	// click the left mouse button
	robotgo.Click()

	// click the right mouse button
	robotgo.Click("right", false)

	// double click the left mouse button
	robotgo.MouseClick("left", true)
}

func get() {
	// gets the mouse coordinates
	x, y := robotgo.GetMousePos()
	fmt.Println("pos:", x, y)
	if x == 456 && y == 586 {
		fmt.Println("mouse...", "586")
	}

	robotgo.MoveMouse(x, y)
}

func toggleAndScroll() {
	// scrolls the mouse either up
	robotgo.ScrollMouse(10, "up")
	robotgo.Scroll(100, 200)

	// toggles right mouse button
	robotgo.MouseToggle("down", "right")

	robotgo.MouseToggle("up")
}

func mouse() {
	////////////////////////////////////////////////////////////////////////////////
	// Control the mouse
	////////////////////////////////////////////////////////////////////////////////

	move()

	click()

	get()

	toggleAndScroll()
}

func main() {
	mouse()
}
<|endoftext|>