<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

type Args struct {
	path   string
	prefix string
}

func isStdLib(name, srcDir string) bool {
	pkg, err := build.Default.Import(name, srcDir, build.FindOnly)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	return pkg.Goroot
}

func getArgs() Args {
	f := flag.String("file", "", "path too a file.")
	prefix := flag.String("prefix", "", "prefix of the local packages.")
	flag.Parse()

	path := *f
	if path == "" {
		flag.Usage()
		os.Exit(1)
	}

	return Args{
		path:   path,
		prefix: *prefix,
	}
}

func loadFile(path string) (*token.FileSet, *ast.File, error) {
	fileSet := token.NewFileSet()
	file, err := parser.ParseFile(fileSet, path, nil, parser.ImportsOnly)
	if err != nil {
		return nil, nil, err
	}

	return fileSet, file, nil
}

func reorderImports(prefix string, srcDir string, file *ast.File) {
	for _, d := range file.Decls {
		genDecl, ok := d.(*ast.GenDecl)
		if !ok {
			continue
		}
		if genDecl.Tok != token.IMPORT {
			continue
		}
		var stdLibAst []ast.Spec
		var localLibAst []ast.Spec
		var otherLibAst []ast.Spec
		for _, s := range genDecl.Specs {
			spec := s.(*ast.ImportSpec)
			name := strings.Trim(spec.Path.Value, `"`)

			if isStdLib(name, srcDir) {
				stdLibAst = append(stdLibAst, spec)
			} else if strings.HasPrefix(name, prefix) {
				localLibAst = append(localLibAst, spec)
			} else {
				otherLibAst = append(otherLibAst, spec)
			}
		}

		sort.Slice(stdLibAst, func(i, j int) bool {
			return stdLibAst[i].(*ast.ImportSpec).Path.Value < stdLibAst[i].(*ast.ImportSpec).Path.Value
		})
		stdLibAst = append(stdLibAst, &ast.ImportSpec{Path: &ast.BasicLit{}})

		sort.Slice(otherLibAst, func(i, j int) bool {
			return otherLibAst[i].(*ast.ImportSpec).Path.Value < otherLibAst[i].(*ast.ImportSpec).Path.Value
		})
		otherLibAst = append(otherLibAst, &ast.ImportSpec{Path: &ast.BasicLit{}})

		sort.Slice(localLibAst, func(i, j int) bool {
			return localLibAst[i].(*ast.ImportSpec).Path.Value < localLibAst[i].(*ast.ImportSpec).Path.Value
		})

		genDecl.Specs = append(append(stdLibAst, otherLibAst...), localLibAst...)
	}

}

func generate(file *ast.File, cm ast.CommentMap) ([]string, map[int]int) {
	importStmts := make([]string, 0)
	parenMap := make(map[int]int)
	for _, d := range file.Decls {
		genDecl, ok := d.(*ast.GenDecl)
		if !ok {
			continue
		}
		if genDecl.Tok != token.IMPORT {
			continue
		}

		if genDecl.Lparen.IsValid() {
			// start from zero.
			parenMap[int(genDecl.Lparen)-1] = int(genDecl.Rparen)
		}

		buf := bytes.NewBufferString("import (\n")
		for _, s := range genDecl.Specs {
			spec := s.(*ast.ImportSpec)

			comments, ok := cm[spec]
			if ok {
				for _, comment := range comments {
					buf.WriteString("\t")
					buf.WriteString(comment.Text())
					buf.WriteString("\n")
				}
			}

			buf.WriteString("\t")
			if spec.Name != nil {
				buf.WriteString(spec.Name.String())
				buf.WriteString(" ")
			}
			buf.WriteString(spec.Path.Value)
			buf.WriteString("\n")
		}
		buf.WriteString(")\n")
		importStmts = append(importStmts, buf.String())
	}

	return importStmts, parenMap
}

func replaceImports(path string, importStmts []string, parenMap map[int]int) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	bodyBytes, err := ioutil.ReadAll(file)
	if err != nil {
		return "", err
	}

	buf := bytes.NewBufferString("")
	for _, imp := range importStmts {
		pos := bytes.Index(bodyBytes, []byte("import"))
		buf.Write(bodyBytes[:pos])

		end := func() int {
			next := string(bodyBytes[pos+6 : pos+7])
			if next != " " && next != "\n" && next != "(" && next != "\t" {
				return -1
			}

			for i := pos + 6; i < len(bodyBytes); i++ {
				c := string(bodyBytes[i : i+1])
				if c == "(" {
					e, ok := parenMap[i]
					if !ok {
						return -1
					}
					return e
				} else if c == " " || c == "\t" || c == "\n" {
					continue
				} else {
					for j := i; j < len(bodyBytes); j++ {
						if string(bodyBytes[j:j+1]) == "\n" {
							return j + 1
						}
					}
				}
			}
			return -1
		}()

		if end < 0 {
			return "", errors.New("Failed to find import statements.")
		}

		buf.WriteString(imp)
		buf.WriteString("\n")
		bodyBytes = bytes.TrimLeft(bodyBytes[end:], " \t\n")
	}

	buf.Write(bodyBytes)

	return buf.String(), nil
}

func main() {
	args := getArgs()

	fileSet, file, err := loadFile(args.path)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	srcDir := filepath.Dir(args.path)
	reorderImports(args.prefix, srcDir, file)

	cm := ast.NewCommentMap(fileSet, file, file.Comments)

	importStmt, parenMap := generate(file, cm)
	replaced, err := replaceImports(args.path, importStmt, parenMap)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	fmt.Fprint(os.Stdout, replaced)
}
<commit_msg>Overwrite file.<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"fmt"
)

type Args struct {
	path   string
	prefix string
	overwrite bool
}

func isStdLib(name, srcDir string) bool {
	pkg, err := build.Default.Import(name, srcDir, build.FindOnly)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	return pkg.Goroot
}

func getArgs() Args {
	f := flag.String("file", "", "path too a file.")
	prefix := flag.String("prefix", "", "prefix of the local packages.")
	overwrite := flag.Bool("w", false, "overwrite file.")
	flag.Parse()

	path := *f
	if path == "" {
		flag.Usage()
		os.Exit(1)
	}

	return Args{
		path:   path,
		prefix: *prefix,
		overwrite: *overwrite,
	}
}

func loadFile(path string) (*token.FileSet, *ast.File, error) {
	fileSet := token.NewFileSet()
	file, err := parser.ParseFile(fileSet, path, nil, parser.ImportsOnly)
	if err != nil {
		return nil, nil, err
	}

	return fileSet, file, nil
}

func reorderImports(prefix string, srcDir string, file *ast.File) {
	for _, d := range file.Decls {
		genDecl, ok := d.(*ast.GenDecl)
		if !ok {
			continue
		}
		if genDecl.Tok != token.IMPORT {
			continue
		}
		var stdLibAst []ast.Spec
		var localLibAst []ast.Spec
		var otherLibAst []ast.Spec
		for _, s := range genDecl.Specs {
			spec := s.(*ast.ImportSpec)
			name := strings.Trim(spec.Path.Value, `"`)

			if isStdLib(name, srcDir) {
				stdLibAst = append(stdLibAst, spec)
			} else if strings.HasPrefix(name, prefix) {
				localLibAst = append(localLibAst, spec)
			} else {
				otherLibAst = append(otherLibAst, spec)
			}
		}

		sort.Slice(stdLibAst, func(i, j int) bool {
			return stdLibAst[i].(*ast.ImportSpec).Path.Value < stdLibAst[i].(*ast.ImportSpec).Path.Value
		})
		stdLibAst = append(stdLibAst, &ast.ImportSpec{Path: &ast.BasicLit{}})

		sort.Slice(otherLibAst, func(i, j int) bool {
			return otherLibAst[i].(*ast.ImportSpec).Path.Value < otherLibAst[i].(*ast.ImportSpec).Path.Value
		})
		otherLibAst = append(otherLibAst, &ast.ImportSpec{Path: &ast.BasicLit{}})

		sort.Slice(localLibAst, func(i, j int) bool {
			return localLibAst[i].(*ast.ImportSpec).Path.Value < localLibAst[i].(*ast.ImportSpec).Path.Value
		})

		genDecl.Specs = append(append(stdLibAst, otherLibAst...), localLibAst...)
	}

}

func generate(file *ast.File, cm ast.CommentMap) ([]string, map[int]int) {
	importStmts := make([]string, 0)
	parenMap := make(map[int]int)
	for _, d := range file.Decls {
		genDecl, ok := d.(*ast.GenDecl)
		if !ok {
			continue
		}
		if genDecl.Tok != token.IMPORT {
			continue
		}

		if genDecl.Lparen.IsValid() {
			// start from zero.
			parenMap[int(genDecl.Lparen)-1] = int(genDecl.Rparen)
		}

		buf := bytes.NewBufferString("import (\n")
		for _, s := range genDecl.Specs {
			spec := s.(*ast.ImportSpec)

			comments, ok := cm[spec]
			if ok {
				for _, comment := range comments {
					buf.WriteString("\t")
					buf.WriteString(comment.Text())
					buf.WriteString("\n")
				}
			}

			buf.WriteString("\t")
			if spec.Name != nil {
				buf.WriteString(spec.Name.String())
				buf.WriteString(" ")
			}
			buf.WriteString(spec.Path.Value)
			buf.WriteString("\n")
		}
		buf.WriteString(")\n")
		importStmts = append(importStmts, buf.String())
	}

	return importStmts, parenMap
}

func replaceImports(path string, importStmts []string, parenMap map[int]int) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	bodyBytes, err := ioutil.ReadAll(file)
	if err != nil {
		return "", err
	}

	buf := bytes.NewBufferString("")
	for _, imp := range importStmts {
		pos := bytes.Index(bodyBytes, []byte("import"))
		buf.Write(bodyBytes[:pos])

		end := func() int {
			next := string(bodyBytes[pos+6 : pos+7])
			if next != " " && next != "\n" && next != "(" && next != "\t" {
				return -1
			}

			for i := pos + 6; i < len(bodyBytes); i++ {
				c := string(bodyBytes[i : i+1])
				if c == "(" {
					e, ok := parenMap[i]
					if !ok {
						return -1
					}
					return e
				} else if c == " " || c == "\t" || c == "\n" {
					continue
				} else {
					for j := i; j < len(bodyBytes); j++ {
						if string(bodyBytes[j:j+1]) == "\n" {
							return j + 1
						}
					}
				}
			}
			return -1
		}()

		if end < 0 {
			return "", errors.New("Failed to find import statements.")
		}

		buf.WriteString(imp)
		buf.WriteString("\n")
		bodyBytes = bytes.TrimLeft(bodyBytes[end:], " \t\n")
	}

	buf.Write(bodyBytes)

	return buf.String(), nil
}

func main() {
	args := getArgs()

	fileSet, file, err := loadFile(args.path)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	srcDir := filepath.Dir(args.path)
	reorderImports(args.prefix, srcDir, file)

	cm := ast.NewCommentMap(fileSet, file, file.Comments)

	importStmt, parenMap := generate(file, cm)
	replaced, err := replaceImports(args.path, importStmt, parenMap)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}

	if args.overwrite {
		err = ioutil.WriteFile(args.path, []byte(replaced), 0644)
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}
	} else {
		_, err := fmt.Fprint(os.Stdout, replaced)
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	"repo"
	"resources"
	"strconv"
	"strings"
)

var port int
var todoRegex string
var excludePaths string

func init() {
	flag.IntVar(&port, "port", 8080, "Port on which to start the server.")
	flag.StringVar(
		&todoRegex,
		"todo_regex",
		"[^[:alpha:]](t|T)(o|O)(d|D)(o|O)[^[:alpha:]]",
		"Regular expression (using the re2 syntax) to use when matching TODOs.")
	flag.StringVar(
		&excludePaths,
		"exclude_paths",
		"",
		"List of file paths to exclude when matching TODOs. This is useful if your repo contains binaries")
}

func serveStaticContent(w http.ResponseWriter, resourceName string) {
	resourceContents := resources.Constants[resourceName]
	var contentType string
	if strings.HasSuffix(resourceName, ".css") {
		contentType = "text/css"
	} else if strings.HasSuffix(resourceName, ".html") {
		contentType = "text/html"
	} else if strings.HasSuffix(resourceName, ".js") {
		contentType = "text/javascript"
	} else {
		contentType = http.DetectContentType(resourceContents)
	}
	w.Header().Set("Content-Type", contentType)
	w.Write(resourceContents)
}

func serveRepoDetails(repository repo.Repository) {
	http.HandleFunc("/ui/", func(w http.ResponseWriter, r *http.Request) {
		resourceName := r.URL.Path[4:]
		serveStaticContent(w, resourceName)
	})
	http.HandleFunc("/aliases",
		func(w http.ResponseWriter, r *http.Request) {
			err := repo.WriteJson(w, repository)
			if err != nil {
				w.WriteHeader(500)
				fmt.Fprintf(w, "Server error \"%s\"", err)
			}
		})
	http.HandleFunc("/revision",
		func(w http.ResponseWriter, r *http.Request) {
			revisionParam := r.URL.Query().Get("id")
			if revisionParam == "" {
				w.WriteHeader(400)
				fmt.Fprint(w, "Missing required parameter 'id'")
				return
			}
			revision := repo.Revision(revisionParam)
			err := repo.WriteTodosJson(w, repository, revision, todoRegex, excludePaths)
			if err != nil {
				w.WriteHeader(500)
				fmt.Fprintf(w, "Server error \"%s\"", err)
			}
		})
	http.HandleFunc("/todo",
		func(w http.ResponseWriter, r *http.Request) {
			revisionParam := r.URL.Query().Get("revision")
			lineNumberParam := r.URL.Query().Get("lineNumber")
			fileName := r.URL.Query().Get("fileName")
			if revisionParam == "" || fileName == "" || lineNumberParam == "" {
				w.WriteHeader(400)
				fmt.Fprintf(w, "Missing at least one required parameter")
				return
			}
			revision := repo.Revision(revisionParam)
			lineNumber, err := strconv.Atoi(lineNumberParam)
			if err != nil {
				w.WriteHeader(400)
				fmt.Fprintf(w, "Invalid format for the lineNumber parameter: %s", err)
				return
			}
			todoId := repo.TodoId{
				Revision:   revision,
				FileName:   fileName,
				LineNumber: lineNumber,
			}
			repo.WriteTodoDetailsJson(w, repository, todoId)
		})
	http.HandleFunc("/",
		func(w http.ResponseWriter, r *http.Request) {
			http.Redirect(w, r, "/ui/list_branches.html", http.StatusMovedPermanently)
		})
	http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

func main() {
	flag.Parse()
	var gitRepository repo.GitRepository
	serveRepoDetails(gitRepository)
}
<commit_msg>Changed the default regex to also match TODOs at the beginning of a line<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	"repo"
	"resources"
	"strconv"
	"strings"
)

var port int
var todoRegex string
var excludePaths string

func init() {
	flag.IntVar(&port, "port", 8080, "Port on which to start the server.")
	flag.StringVar(
		&todoRegex,
		"todo_regex",
		"(^|[^[:alpha:]])(t|T)(o|O)(d|D)(o|O)[^[:alpha:]]",
		"Regular expression (using the re2 syntax) to use when matching TODOs.")
	flag.StringVar(
		&excludePaths,
		"exclude_paths",
		"",
		"List of file paths to exclude when matching TODOs. This is useful if your repo contains binaries")
}

func serveStaticContent(w http.ResponseWriter, resourceName string) {
	resourceContents := resources.Constants[resourceName]
	var contentType string
	if strings.HasSuffix(resourceName, ".css") {
		contentType = "text/css"
	} else if strings.HasSuffix(resourceName, ".html") {
		contentType = "text/html"
	} else if strings.HasSuffix(resourceName, ".js") {
		contentType = "text/javascript"
	} else {
		contentType = http.DetectContentType(resourceContents)
	}
	w.Header().Set("Content-Type", contentType)
	w.Write(resourceContents)
}

func serveRepoDetails(repository repo.Repository) {
	http.HandleFunc("/ui/", func(w http.ResponseWriter, r *http.Request) {
		resourceName := r.URL.Path[4:]
		serveStaticContent(w, resourceName)
	})
	http.HandleFunc("/aliases",
		func(w http.ResponseWriter, r *http.Request) {
			err := repo.WriteJson(w, repository)
			if err != nil {
				w.WriteHeader(500)
				fmt.Fprintf(w, "Server error \"%s\"", err)
			}
		})
	http.HandleFunc("/revision",
		func(w http.ResponseWriter, r *http.Request) {
			revisionParam := r.URL.Query().Get("id")
			if revisionParam == "" {
				w.WriteHeader(400)
				fmt.Fprint(w, "Missing required parameter 'id'")
				return
			}
			revision := repo.Revision(revisionParam)
			err := repo.WriteTodosJson(w, repository, revision, todoRegex, excludePaths)
			if err != nil {
				w.WriteHeader(500)
				fmt.Fprintf(w, "Server error \"%s\"", err)
			}
		})
	http.HandleFunc("/todo",
		func(w http.ResponseWriter, r *http.Request) {
			revisionParam := r.URL.Query().Get("revision")
			lineNumberParam := r.URL.Query().Get("lineNumber")
			fileName := r.URL.Query().Get("fileName")
			if revisionParam == "" || fileName == "" || lineNumberParam == "" {
				w.WriteHeader(400)
				fmt.Fprintf(w, "Missing at least one required parameter")
				return
			}
			revision := repo.Revision(revisionParam)
			lineNumber, err := strconv.Atoi(lineNumberParam)
			if err != nil {
				w.WriteHeader(400)
				fmt.Fprintf(w, "Invalid format for the lineNumber parameter: %s", err)
				return
			}
			todoId := repo.TodoId{
				Revision:   revision,
				FileName:   fileName,
				LineNumber: lineNumber,
			}
			repo.WriteTodoDetailsJson(w, repository, todoId)
		})
	http.HandleFunc("/",
		func(w http.ResponseWriter, r *http.Request) {
			http.Redirect(w, r, "/ui/list_branches.html", http.StatusMovedPermanently)
		})
	http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

func main() {
	flag.Parse()
	var gitRepository repo.GitRepository
	serveRepoDetails(gitRepository)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Tekton 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 v1alpha1_test

import (
	"context"
	"testing"

	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
	tb "github.com/tektoncd/pipeline/test/builder"
)

func TestPipeline_Validate_Error(t *testing.T) {
	tests := []struct {
		name string
		p    *v1alpha1.Pipeline
	}{
		{
			name: "period in name",
			p: tb.Pipeline("pipe.line", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task"),
			)),
		},
		{
			name: "pipeline name too long",
			p: tb.Pipeline("asdf123456789012345678901234567890123456789012345678901234567890", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task"),
			)),
		},
		{
			name: "pipeline spec invalid (duplicate tasks)",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task"),
				tb.PipelineTask("foo", "foo-task"),
			)),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := tt.p.Validate(context.Background()); err == nil {
				t.Error("Pipeline.Validate() did not return error, wanted error")
			}
		})
	}
}

func TestPipeline_Validate_Valid(t *testing.T) {
	tests := []struct {
		name string
		p    *v1alpha1.Pipeline
	}{
		{
			name: "valid metadata",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task"),
			)),
		},
		{
			name: "valid resource declarations and usage",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
				tb.PipelineTask("bar", "bar-task",
					tb.PipelineTaskInputResource("some-workspace", "great-resource"),
					tb.PipelineTaskOutputResource("some-image", "wonderful-resource")),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("wow-image", "wonderful-resource", tb.From("bar"))),
			)),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := tt.p.Spec.Validate(context.Background()); err != nil {
				t.Errorf("Pipeline.Validate() returned error: %v", err)
			}
		})
	}
}

func TestPipelineSpec_Validate_Error(t *testing.T) {
	tests := []struct {
		name string
		p    *v1alpha1.Pipeline
	}{
		{
			name: "duplicate tasks",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task"),
				tb.PipelineTask("foo", "foo-task"),
			)),
		},
		{
			name: "from is on first task",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("the-resource", "great-resource", tb.From("bar"))),
			)),
		},
		{
			name: "from task doesnt exist",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineTask("baz", "baz-task"),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("the-resource", "great-resource", tb.From("bar"))),
			)),
		},
		{
			name: "unused resources declared",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineDeclaredResource("extra-resource", v1alpha1.PipelineResourceTypeImage),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("the-resource", "great-resource")),
			)),
		},
		{
			name: "output resources missing from declaration",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("the-resource", "great-resource"),
					tb.PipelineTaskOutputResource("the-magic-resource", "missing-resource")),
			)),
		},
		{
			name: "input resources missing from declaration",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("the-resource", "missing-resource"),
					tb.PipelineTaskOutputResource("the-magic-resource", "great-resource")),
			)),
		},
		{
			name: "from resource isn't output by task",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
				tb.PipelineTask("bar", "bar-task",
					tb.PipelineTaskInputResource("some-workspace", "great-resource")),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("wow-image", "wonderful-resource", tb.From("bar"))),
			)),
		},
		{
			name: "not defined parameter variable",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskParam("a-param", "${params.does-not-exist}")))),
		},
		{
			name: "not defined parameter variable with defined",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineParam("foo", tb.PipelineParamDefault("something")),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskParam("a-param", "${params.foo} and ${params.does-not-exist}")))),
		},
		{
			name: "invalid dependency graph between the tasks",
			p: tb.Pipeline("foo", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo", tb.RunAfter("bar")),
				tb.PipelineTask("bar", "bar", tb.RunAfter("foo")),
			)),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := tt.p.Spec.Validate(context.Background()); err == nil {
				t.Error("PipelineSpec.Validate() did not return error, wanted error")
			}
		})
	}
}

func TestPipelineSpec_Validate_Valid(t *testing.T) {
	tests := []struct {
		name string
		p    *v1alpha1.Pipeline
	}{
		{
			name: "no duplicate tasks",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineTask("foo", "foo-task"),
				tb.PipelineTask("bar", "bar-task"),
			)),
		},
		{
			// Adding this case because `task.Resources` is a pointer, explicitly making sure this is handled
			name: "task without resources",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
				tb.PipelineTask("bar", "bar-task"),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("wow-image", "wonderful-resource")),
			)),
		},
		{
			name: "valid resource declarations and usage",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
				tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
				tb.PipelineTask("bar", "bar-task",
					tb.PipelineTaskInputResource("some-workspace", "great-resource"),
					tb.PipelineTaskOutputResource("some-image", "wonderful-resource")),
				tb.PipelineTask("foo", "foo-task",
					tb.PipelineTaskInputResource("wow-image", "wonderful-resource", tb.From("bar"))),
			)),
		},
		{
			name: "valid parameter variables",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineParam("baz"),
				tb.PipelineParam("foo-is-baz"),
				tb.PipelineTask("bar", "bar-task",
					tb.PipelineTaskParam("a-param", "${baz} and ${foo-is-baz}")),
			)),
		},
		{
			name: "pipeline parameter nested in task parameter",
			p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
				tb.PipelineParam("baz"),
				tb.PipelineTask("bar", "bar-task",
					tb.PipelineTaskParam("a-param", "${input.workspace.${baz}}")),
			)),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := tt.p.Spec.Validate(context.Background()); err != nil {
				t.Errorf("PipelineSpec.Validate() returned error: %v", err)
			}
		})
	}
}
<commit_msg>Combine pipeline verification success/error tests.<commit_after>/*
Copyright 2019 The Tekton 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 v1alpha1_test

import (
	"context"
	"testing"

	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
	tb "github.com/tektoncd/pipeline/test/builder"
)

func TestPipeline_Validate(t *testing.T) {
	tests := []struct {
		name            string
		p               *v1alpha1.Pipeline
		failureExpected bool
	}{{
		name: "valid metadata",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task"),
		)),
		failureExpected: false,
	}, {
		name: "valid resource declarations and usage",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
			tb.PipelineTask("bar", "bar-task",
				tb.PipelineTaskInputResource("some-workspace", "great-resource"),
				tb.PipelineTaskOutputResource("some-image", "wonderful-resource")),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("wow-image", "wonderful-resource", tb.From("bar"))),
		)),
		failureExpected: false,
	}, {
		name: "period in name",
		p: tb.Pipeline("pipe.line", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task"),
		)),
		failureExpected: true,
	}, {
		name: "pipeline name too long",
		p: tb.Pipeline("asdf123456789012345678901234567890123456789012345678901234567890", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task"),
		)),
		failureExpected: true,
	}, {
		name: "pipeline spec invalid (duplicate tasks)",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task"),
			tb.PipelineTask("foo", "foo-task"),
		)),
		failureExpected: true,
	}}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.p.Validate(context.Background())
			if (!tt.failureExpected) && (err != nil) {
				t.Errorf("Pipeline.Validate() returned error: %v", err)
			}

			if tt.failureExpected && (err == nil) {
				t.Error("Pipeline.Validate() did not return error, wanted error")
			}
		})
	}
}

func TestPipelineSpec_Validate(t *testing.T) {
	tests := []struct {
		name            string
		p               *v1alpha1.Pipeline
		failureExpected bool
	}{{
		name: "no duplicate tasks",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task"),
			tb.PipelineTask("bar", "bar-task"),
		)),
		failureExpected: false,
	}, {
		// Adding this case because `task.Resources` is a pointer, explicitly making sure this is handled
		name: "task without resources",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
			tb.PipelineTask("bar", "bar-task"),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("wow-image", "wonderful-resource")),
		)),
		failureExpected: false,
	}, {
		name: "valid resource declarations and usage",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
			tb.PipelineTask("bar", "bar-task",
				tb.PipelineTaskInputResource("some-workspace", "great-resource"),
				tb.PipelineTaskOutputResource("some-image", "wonderful-resource")),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("wow-image", "wonderful-resource", tb.From("bar"))),
		)),
		failureExpected: false,
	}, {
		name: "valid parameter variables",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineParam("baz"),
			tb.PipelineParam("foo-is-baz"),
			tb.PipelineTask("bar", "bar-task",
				tb.PipelineTaskParam("a-param", "${baz} and ${foo-is-baz}")),
		)),
		failureExpected: false,
	}, {
		name: "pipeline parameter nested in task parameter",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineParam("baz"),
			tb.PipelineTask("bar", "bar-task",
				tb.PipelineTaskParam("a-param", "${input.workspace.${baz}}")),
		)),
		failureExpected: false,
	}, {
		name: "duplicate tasks",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task"),
			tb.PipelineTask("foo", "foo-task"),
		)),
		failureExpected: true,
	}, {
		name: "from is on first task",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("the-resource", "great-resource", tb.From("bar"))),
		)),
		failureExpected: true,
	}, {
		name: "from task doesnt exist",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineTask("baz", "baz-task"),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("the-resource", "great-resource", tb.From("bar"))),
		)),
		failureExpected: true,
	}, {
		name: "unused resources declared",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineDeclaredResource("extra-resource", v1alpha1.PipelineResourceTypeImage),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("the-resource", "great-resource")),
		)),
		failureExpected: true,
	}, {
		name: "output resources missing from declaration",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("the-resource", "great-resource"),
				tb.PipelineTaskOutputResource("the-magic-resource", "missing-resource")),
		)),
		failureExpected: true,
	}, {
		name: "input resources missing from declaration",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("the-resource", "missing-resource"),
				tb.PipelineTaskOutputResource("the-magic-resource", "great-resource")),
		)),
		failureExpected: true,
	}, {
		name: "from resource isn't output by task",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineDeclaredResource("great-resource", v1alpha1.PipelineResourceTypeGit),
			tb.PipelineDeclaredResource("wonderful-resource", v1alpha1.PipelineResourceTypeImage),
			tb.PipelineTask("bar", "bar-task",
				tb.PipelineTaskInputResource("some-workspace", "great-resource")),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskInputResource("wow-image", "wonderful-resource", tb.From("bar"))),
		)),
		failureExpected: true,
	}, {
		name: "not defined parameter variable",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskParam("a-param", "${params.does-not-exist}")))),
		failureExpected: true,
	}, {
		name: "not defined parameter variable with defined",
		p: tb.Pipeline("pipeline", "namespace", tb.PipelineSpec(
			tb.PipelineParam("foo", tb.PipelineParamDefault("something")),
			tb.PipelineTask("foo", "foo-task",
				tb.PipelineTaskParam("a-param", "${params.foo} and ${params.does-not-exist}")))),
		failureExpected: true,
	}, {
		name: "invalid dependency graph between the tasks",
		p: tb.Pipeline("foo", "namespace", tb.PipelineSpec(
			tb.PipelineTask("foo", "foo", tb.RunAfter("bar")),
			tb.PipelineTask("bar", "bar", tb.RunAfter("foo")),
		)),
		failureExpected: true,
	}}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.p.Spec.Validate(context.Background())
			if (!tt.failureExpected) && (err != nil) {
				t.Errorf("PipelineSpec.Validate() returned error: %v", err)
			}

			if tt.failureExpected && (err == nil) {
				t.Error("PipelineSpec.Validate() did not return error, wanted error")
			}
		})
	}
}
<|endoftext|>


<commit_before>package page

import (
	"net/http"

	"github.com/gorilla/mux"
	"github.com/zachlatta/go-mailpin/model"
	"github.com/zachlatta/go-mailpin/view"

	"appengine"
)

func View(w http.ResponseWriter, r *http.Request) *model.AppError {
	c := appengine.NewContext(r)
	vars := mux.Vars(r)
	id := vars["id"]

	page, err := model.GetPage(c, id)
	if err != nil {
		return &model.AppError{err, "Page not found", http.StatusNotFound}
	}

	return view.RenderTemplate(w, "page", page)
}
<commit_msg>404 not found on favicon.ico<commit_after>package page

import (
	"net/http"

	"github.com/gorilla/mux"
	"github.com/zachlatta/go-mailpin/model"
	"github.com/zachlatta/go-mailpin/view"

	"appengine"
)

func View(w http.ResponseWriter, r *http.Request) *model.AppError {
	c := appengine.NewContext(r)
	vars := mux.Vars(r)
	id := vars["id"]

	if id == "favicon.ico" {
		http.Error(w, "404 not found", http.StatusNotFound)
		return nil
	}

	page, err := model.GetPage(c, id)
	if err != nil {
		return &model.AppError{err, "Page not found", http.StatusNotFound}
	}

	return view.RenderTemplate(w, "page", page)
}
<|endoftext|>


<commit_before>package stripe

import (
	"socialapi/workers/payment/paymenterrors"
	"socialapi/workers/payment/paymentmodels"

	stripe "github.com/stripe/stripe-go"
	stripeCard "github.com/stripe/stripe-go/card"
	stripeCustomer "github.com/stripe/stripe-go/customer"
)

type CreditCardResponse struct {
	LastFour string `json:"last4"`
	Month    uint8  `json:"month"`
	Year     uint16 `json:"year"`
	Name     string `json:"name"`
}

func GetCreditCard(oldId string) (*CreditCardResponse, error) {
	customer, err := paymentmodels.NewCustomer().ByOldId(oldId)
	if err != nil {
		return nil, err
	}

	externalCustomer, err := GetCustomer(customer.ProviderCustomerId)
	if err != nil {
		return nil, err
	}

	creditCardList := externalCustomer.Cards
	if IsNoCreditCards(creditCardList) {
		return &CreditCardResponse{}, nil
	}

	if IsTooManyCreditCards(creditCardList) {
		Log.Error(
			"Customer (stripe): %s has too many: %s credit cards.",
			customer.ProviderCustomerId, creditCardList.Count,
		)
	}

	creditCard := creditCardList.Values[0]
	creditCardResponse := &CreditCardResponse{
		LastFour: creditCard.LastFour,
		Month:    creditCard.Month,
		Year:     creditCard.Year,
		Name:     creditCard.Name,
	}

	return creditCardResponse, nil
}

func UpdateCreditCard(oldId, token string) error {
	if IsEmpty(token) {
		return paymenterrors.ErrTokenIsEmpty
	}

	customer, err := paymentmodels.NewCustomer().ByOldId(oldId)
	if err != nil {
		return err
	}

	customerParams := &stripe.CustomerParams{Token: token}

	_, err = stripeCustomer.Update(customer.ProviderCustomerId, customerParams)
	if err != nil {
		return handleStripeError(err)
	}

	return nil
}

func RemoveCreditCard(customer *paymentmodels.Customer) error {
	externalCustomer, err := GetCustomer(customer.ProviderCustomerId)
	if err != nil {
		return err
	}

	creditCardList := externalCustomer.Cards
	if IsNoCreditCards(creditCardList) {
		return paymenterrors.ErrNoCreditCard
	}

	if IsTooManyCreditCards(creditCardList) {
		Log.Error(
			"Customer (stripe): %s has too many: %s credit cards.",
			customer.ProviderCustomerId, creditCardList.Count,
		)
	}

	creditCard := creditCardList.Values[0]

	creditCardParams := &stripe.CardParams{
		Customer: externalCustomer.Id,
	}
	err = stripeCard.Del(creditCard.Id, creditCardParams)

	return err
}

func UpdateCreditCardIfEmpty(accId, token string) error {
	ccResp, err := GetCreditCard(accId)
	if err != nil {
		return err
	}

	if IsCreditCardEmpty(ccResp) {
		err := UpdateCreditCard(accId, token)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>payment: return type of card as brand<commit_after>package stripe

import (
	"socialapi/workers/payment/paymenterrors"
	"socialapi/workers/payment/paymentmodels"

	stripe "github.com/stripe/stripe-go"
	stripeCard "github.com/stripe/stripe-go/card"
	stripeCustomer "github.com/stripe/stripe-go/customer"
)

type CreditCardResponse struct {
	LastFour string `json:"last4"`
	Month    uint8  `json:"month"`
	Year     uint16 `json:"year"`
	Name     string `json:"name"`
	Brand    string `json:"brand"`
}

func GetCreditCard(oldId string) (*CreditCardResponse, error) {
	customer, err := paymentmodels.NewCustomer().ByOldId(oldId)
	if err != nil {
		return nil, err
	}

	externalCustomer, err := GetCustomer(customer.ProviderCustomerId)
	if err != nil {
		return nil, err
	}

	creditCardList := externalCustomer.Cards
	if IsNoCreditCards(creditCardList) {
		return &CreditCardResponse{}, nil
	}

	if IsTooManyCreditCards(creditCardList) {
		Log.Error(
			"Customer (stripe): %s has too many: %s credit cards.",
			customer.ProviderCustomerId, creditCardList.Count,
		)
	}

	creditCard := creditCardList.Values[0]
	creditCardResponse := &CreditCardResponse{
		LastFour: creditCard.LastFour,
		Month:    creditCard.Month,
		Year:     creditCard.Year,
		Name:     creditCard.Name,
		Brand:    string(creditCard.Brand),
	}

	return creditCardResponse, nil
}

func UpdateCreditCard(oldId, token string) error {
	if IsEmpty(token) {
		return paymenterrors.ErrTokenIsEmpty
	}

	customer, err := paymentmodels.NewCustomer().ByOldId(oldId)
	if err != nil {
		return err
	}

	customerParams := &stripe.CustomerParams{Token: token}

	_, err = stripeCustomer.Update(customer.ProviderCustomerId, customerParams)
	if err != nil {
		return handleStripeError(err)
	}

	return nil
}

func RemoveCreditCard(customer *paymentmodels.Customer) error {
	externalCustomer, err := GetCustomer(customer.ProviderCustomerId)
	if err != nil {
		return err
	}

	creditCardList := externalCustomer.Cards
	if IsNoCreditCards(creditCardList) {
		return paymenterrors.ErrNoCreditCard
	}

	if IsTooManyCreditCards(creditCardList) {
		Log.Error(
			"Customer (stripe): %s has too many: %s credit cards.",
			customer.ProviderCustomerId, creditCardList.Count,
		)
	}

	creditCard := creditCardList.Values[0]

	creditCardParams := &stripe.CardParams{
		Customer: externalCustomer.Id,
	}
	err = stripeCard.Del(creditCard.Id, creditCardParams)

	return err
}

func UpdateCreditCardIfEmpty(accId, token string) error {
	ccResp, err := GetCreditCard(accId)
	if err != nil {
		return err
	}

	if IsCreditCardEmpty(ccResp) {
		err := UpdateCreditCard(accId, token)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package config

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/topicai/candy"
	"gopkg.in/yaml.v2"
)

func TestInitialEtcdCluster(t *testing.T) {
	c := &Cluster{}
	candy.Must(yaml.Unmarshal([]byte(ExampleYAML), c))
	assert.Equal(t,
		c.InitialEtcdCluster(),
		"00-25-90-c0-f7-80=http://10.0.2.21:2380,"+
			"00-25-90-c0-f6-ee=http://10.0.2.22:2380,"+
			"00-25-90-c0-f6-d6=http://00-25-90-c0-f6-d6:2380")
}

func TestGetEtcdMachines(t *testing.T) {
	c := &Cluster{}
	candy.Must(yaml.Unmarshal([]byte(ExampleYAML), c))
	assert.Equal(t, c.GetEtcdMachines(),
		"http://172.17.0.10:2379,http://172.17.0.11:2379")
}
<commit_msg>Update etcd_test.go with the change of ExampleYAML<commit_after>package config

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/topicai/candy"
	"gopkg.in/yaml.v2"
)

func TestInitialEtcdCluster(t *testing.T) {
	c := &Cluster{}
	candy.Must(yaml.Unmarshal([]byte(ExampleYAML), c))
	assert.Equal(t,
		c.InitialEtcdCluster(),
		"00-25-90-c0-f7-80=http://10.0.2.21:2380,"+
			"00-25-90-c0-f6-ee=http://10.0.2.22:2380,"+
			"00-25-90-c0-f6-d6=http://00-25-90-c0-f6-d6:2380")
}

func TestGetEtcdMachines(t *testing.T) {
	c := &Cluster{}
	candy.Must(yaml.Unmarshal([]byte(ExampleYAML), c))
	assert.Equal(t, c.GetEtcdMachines(),
		"http://10.0.2.21:2379,http://10.0.2.22:2379")
}
<|endoftext|>


<commit_before>package network

import (
	"context"
	"time"
)

// DialPeerTimeout is the default timeout for a single call to `DialPeer`. When
// there are multiple concurrent calls to `DialPeer`, this timeout will apply to
// each independently.
var DialPeerTimeout = 60 * time.Second

type noDialCtxKey struct{}
type dialPeerTimeoutCtxKey struct{}

var noDial = noDialCtxKey{}

// WithNoDial constructs a new context with an option that instructs the network
// to not attempt a new dial when opening a stream.
func WithNoDial(ctx context.Context, reason string) context.Context {
	return context.WithValue(ctx, noDial, reason)
}

// GetNoDial returns true if the no dial option is set in the context.
func GetNoDial(ctx context.Context) (nodial bool, reason string) {
	v := ctx.Value(noDial)
	if v != nil {
		return true, v.(string)
	}

	return false, ""
}

// GetDialPeerTimeout returns the current DialPeer timeout (or the default).
func GetDialPeerTimeout(ctx context.Context) time.Duration {
	if to, ok := ctx.Value(dialPeerTimeoutCtxKey{}).(time.Duration); ok {
		return to
	}
	return DialPeerTimeout
}

// WithDialPeerTimeout returns a new context with the DialPeer timeout applied.
//
// This timeout overrides the default DialPeerTimeout and applies per-dial
// independently.
func WithDialPeerTimeout(ctx context.Context, timeout time.Duration) context.Context {
	return context.WithValue(ctx, dialPeerTimeoutCtxKey{}, timeout)
}
<commit_msg>context to force direct dial (#181)<commit_after>package network

import (
	"context"
	"time"
)

// DialPeerTimeout is the default timeout for a single call to `DialPeer`. When
// there are multiple concurrent calls to `DialPeer`, this timeout will apply to
// each independently.
var DialPeerTimeout = 60 * time.Second

type noDialCtxKey struct{}
type dialPeerTimeoutCtxKey struct{}
type forceDirectDialCtxKey struct{}

var noDial = noDialCtxKey{}
var forceDirectDial = forceDirectDialCtxKey{}

// EXPERIMENTAL
// WithForceDirectDial constructs a new context with an option that instructs the network
// to attempt to force a direct connection to a peer via a dial even if a proxied connection to it already exists.
func WithForceDirectDial(ctx context.Context, reason string) context.Context {
	return context.WithValue(ctx, forceDirectDial, reason)
}

// EXPERIMENTAL
// GetForceDirectDial returns true if the force direct dial option is set in the context.
func GetForceDirectDial(ctx context.Context) (forceDirect bool, reason string) {
	v := ctx.Value(forceDirectDial)
	if v != nil {
		return true, v.(string)
	}

	return false, ""
}

// WithNoDial constructs a new context with an option that instructs the network
// to not attempt a new dial when opening a stream.
func WithNoDial(ctx context.Context, reason string) context.Context {
	return context.WithValue(ctx, noDial, reason)
}

// GetNoDial returns true if the no dial option is set in the context.
func GetNoDial(ctx context.Context) (nodial bool, reason string) {
	v := ctx.Value(noDial)
	if v != nil {
		return true, v.(string)
	}

	return false, ""
}

// GetDialPeerTimeout returns the current DialPeer timeout (or the default).
func GetDialPeerTimeout(ctx context.Context) time.Duration {
	if to, ok := ctx.Value(dialPeerTimeoutCtxKey{}).(time.Duration); ok {
		return to
	}
	return DialPeerTimeout
}

// WithDialPeerTimeout returns a new context with the DialPeer timeout applied.
//
// This timeout overrides the default DialPeerTimeout and applies per-dial
// independently.
func WithDialPeerTimeout(ctx context.Context, timeout time.Duration) context.Context {
	return context.WithValue(ctx, dialPeerTimeoutCtxKey{}, timeout)
}
<|endoftext|>


<commit_before>package srv

import (
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

const helpMessage = `@telepyth\_bot is Telegram notifications in Python.

*Avaliable commands*:
/start begin interaction and issue new token.
/revoke revoke token issued before.
/last send currently valid token or nothing.
/help show help message and credentials.

See source code and more examples on [github page](https://github.com/daskol/telepyth).`

type TelePyth struct {
	Api     *TelegramBotApi
	Storage *Storage

	Polling bool
	Timeout int
}

func (t *TelePyth) HandleTelegramUpdate(update *Update) {
	log.Println("update from", update.Message.From.Id)

	switch update.Message.Text {
	case "/start":
		log.Println(update.Message.From.Id, "send /start")
		token, err := t.Storage.InsertUser(&update.Message.From)

		if err != nil {
			//  TODO: log error and ask try again
			log.Println(err)
			return
		}

		err = (&SendMessage{
			ChatId:    update.Message.From.Id,
			Text:      "Your access token is `" + token + "`.",
			ParseMode: "Markdown",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	case "/last":
		log.Println(update.Message.From.Id, "send /last")
		token, err := t.Storage.SelectTokenBy(&update.Message.From)

		if err != nil {
			log.Println(err)
			return
		}

		err = (&SendMessage{
			ChatId:    update.Message.From.Id,
			Text:      "Your last valid token is `" + token + "`.",
			ParseMode: "Markdown",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	case "/revoke":
		log.Println(update.Message.From.Id, "send /revoke")
		err := (&SendMessage{
			ChatId: update.Message.From.Id,
			Text:   "Not implemented yet.",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	case "/help":
		log.Println(update.Message.From.Id, "send /help")
		err := (&SendMessage{
			ChatId:    update.Message.From.Id,
			Text:      helpMessage,
			ParseMode: "Markdown",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	default:
		log.Println(update.Message.From.Id, "send unknown command")
		err := (&SendMessage{
			ChatId: update.Message.From.Id,
			Text:   "Unknown command. Try /help to see usage details.",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	}
}

func (t *TelePyth) HandleWebhookRequest(w http.ResponseWriter, req *http.Request) {
	log.Println("HandleWebhookRequest(): not implemented!")
}

func (t *TelePyth) HandleNotifyRequest(w http.ResponseWriter, req *http.Request) {
	// validate request method
	if req.Method != "POST" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// check that content type is plain/text
	if contentType, ok := req.Header["Content-Type"]; !ok {
		w.WriteHeader(http.StatusBadRequest)
		return
	} else if contentType[0] == "plain/text" ||
		strings.HasPrefix(contentType[0], "plain/text; ") {
		// TODO: refactor this check
		// do nothing here
	} else {
		for k, v := range contentType {
			log.Println(k, v)
		}
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// split string to extract token
	token := strings.TrimPrefix(req.RequestURI, "/api/notify/")

	if len(token) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// get user by token
	user, err := t.Storage.SelectUserBy(token)

	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	log.Println("user", user.Id, "notify with token", token)

	// extract message text
	bytes, err := ioutil.ReadAll(req.Body)

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

	// send notification to user
	err = (&SendMessage{
		ChatId: user.Id,
		Text:   string(bytes),
	}).To(t.Api)

	if err != nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}
}

func (t *TelePyth) HandlePingRequest(w http.ResponseWriter, req *http.Request) {
	// validate request method
	if req.Method != "GET" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// write response
	pong := []byte("Pong.\n")

	if bytes, err := w.Write(pong); err != nil || bytes != len(pong) {
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (t *TelePyth) PollUpdates() {
	offset := 0

	for {
		updates, err := t.Api.GetUpdates(offset, 100, t.Timeout, nil)

		if err != nil {
			//  TODO: more logging
			log.Println(err)
		}

		for _, update := range updates {
			t.HandleTelegramUpdate(&update)

			if update.UpdateId >= offset {
				offset = update.UpdateId + 1
			}
		}
	}
}

func (t *TelePyth) Serve() error {
	// run go-routing for long polling
	if t.Polling {
		log.Println("poling:", t.Polling)
		log.Println("timeout: ", t.Timeout)

		go t.PollUpdates()
	}

	// run http server
	mux := http.NewServeMux()
	mux.HandleFunc("/api/notify/", t.HandleNotifyRequest)
	mux.HandleFunc("/api/ping/", t.HandlePingRequest)
	mux.HandleFunc("/api/webhook/"+t.Api.GetToken(), t.HandleWebhookRequest)

	srv := http.Server{
		Addr:    ":8080",
		Handler: mux,
	}

	return srv.ListenAndServe()
}
<commit_msg>Force notification with markdown parse mode.<commit_after>package srv

import (
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

const helpMessage = `@telepyth\_bot is Telegram notifications in Python.

*Avaliable commands*:
/start begin interaction and issue new token.
/revoke revoke token issued before.
/last send currently valid token or nothing.
/help show help message and credentials.

See source code and more examples on [github page](https://github.com/daskol/telepyth).`

type TelePyth struct {
	Api     *TelegramBotApi
	Storage *Storage

	Polling bool
	Timeout int
}

func (t *TelePyth) HandleTelegramUpdate(update *Update) {
	log.Println("update from", update.Message.From.Id)

	switch update.Message.Text {
	case "/start":
		log.Println(update.Message.From.Id, "send /start")
		token, err := t.Storage.InsertUser(&update.Message.From)

		if err != nil {
			//  TODO: log error and ask try again
			log.Println(err)
			return
		}

		err = (&SendMessage{
			ChatId:    update.Message.From.Id,
			Text:      "Your access token is `" + token + "`.",
			ParseMode: "Markdown",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	case "/last":
		log.Println(update.Message.From.Id, "send /last")
		token, err := t.Storage.SelectTokenBy(&update.Message.From)

		if err != nil {
			log.Println(err)
			return
		}

		err = (&SendMessage{
			ChatId:    update.Message.From.Id,
			Text:      "Your last valid token is `" + token + "`.",
			ParseMode: "Markdown",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	case "/revoke":
		log.Println(update.Message.From.Id, "send /revoke")
		err := (&SendMessage{
			ChatId: update.Message.From.Id,
			Text:   "Not implemented yet.",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	case "/help":
		log.Println(update.Message.From.Id, "send /help")
		err := (&SendMessage{
			ChatId:    update.Message.From.Id,
			Text:      helpMessage,
			ParseMode: "Markdown",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	default:
		log.Println(update.Message.From.Id, "send unknown command")
		err := (&SendMessage{
			ChatId: update.Message.From.Id,
			Text:   "Unknown command. Try /help to see usage details.",
		}).To(t.Api)

		if err != nil {
			log.Println("error: ", err)
		}
	}
}

func (t *TelePyth) HandleWebhookRequest(w http.ResponseWriter, req *http.Request) {
	log.Println("HandleWebhookRequest(): not implemented!")
}

func (t *TelePyth) HandleNotifyRequest(w http.ResponseWriter, req *http.Request) {
	// validate request method
	if req.Method != "POST" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// check that content type is plain/text
	if contentType, ok := req.Header["Content-Type"]; !ok {
		w.WriteHeader(http.StatusBadRequest)
		return
	} else if contentType[0] == "plain/text" ||
		strings.HasPrefix(contentType[0], "plain/text; ") {
		// TODO: refactor this check
		// do nothing here
	} else {
		for k, v := range contentType {
			log.Println(k, v)
		}
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// split string to extract token
	token := strings.TrimPrefix(req.RequestURI, "/api/notify/")

	if len(token) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// get user by token
	user, err := t.Storage.SelectUserBy(token)

	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	log.Println("user", user.Id, "notify with token", token)

	// extract message text
	bytes, err := ioutil.ReadAll(req.Body)

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

	// send notification to user
	err = (&SendMessage{
		ChatId:    user.Id,
		Text:      string(bytes),
		ParseMode: "Markdown",
	}).To(t.Api)

	if err != nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}
}

func (t *TelePyth) HandlePingRequest(w http.ResponseWriter, req *http.Request) {
	// validate request method
	if req.Method != "GET" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// write response
	pong := []byte("Pong.\n")

	if bytes, err := w.Write(pong); err != nil || bytes != len(pong) {
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (t *TelePyth) PollUpdates() {
	offset := 0

	for {
		updates, err := t.Api.GetUpdates(offset, 100, t.Timeout, nil)

		if err != nil {
			//  TODO: more logging
			log.Println(err)
		}

		for _, update := range updates {
			t.HandleTelegramUpdate(&update)

			if update.UpdateId >= offset {
				offset = update.UpdateId + 1
			}
		}
	}
}

func (t *TelePyth) Serve() error {
	// run go-routing for long polling
	if t.Polling {
		log.Println("poling:", t.Polling)
		log.Println("timeout: ", t.Timeout)

		go t.PollUpdates()
	}

	// run http server
	mux := http.NewServeMux()
	mux.HandleFunc("/api/notify/", t.HandleNotifyRequest)
	mux.HandleFunc("/api/ping/", t.HandlePingRequest)
	mux.HandleFunc("/api/webhook/"+t.Api.GetToken(), t.HandleWebhookRequest)

	srv := http.Server{
		Addr:    ":8080",
		Handler: mux,
	}

	return srv.ListenAndServe()
}
<|endoftext|>


<commit_before>package sshproxy

import (
	"code.google.com/p/go.crypto/ssh"
	"io"
	"log"
	"net"
)

type SshConn struct {
	net.Conn
	config     *ssh.ServerConfig
	callbackFn func(c ssh.ConnMetadata) (*ssh.Client, error)
	wrapFn     func(c ssh.ConnMetadata, r io.ReadCloser) (io.ReadCloser, error)
	closeFn    func(c ssh.ConnMetadata) error
}

func (p *SshConn) serve() error {
	serverConn, chans, reqs, err := ssh.NewServerConn(p, p.config)
	if err != nil {
		log.Println("failed to handshake")
		return (err)
	}

	defer serverConn.Close()

	clientConn, err := p.callbackFn(serverConn)
	if err != nil {
		log.Printf("%s", err.Error())
		return (err)
	}

	defer clientConn.Close()

	go ssh.DiscardRequests(reqs)

	for newChannel := range chans {

		channel2, requests2, err2 := clientConn.OpenChannel(newChannel.ChannelType(), newChannel.ExtraData())
		if err2 != nil {
			log.Printf("Could not accept client channel: %s", err.Error())
			return err
		}

		channel, requests, err := newChannel.Accept()
		if err != nil {
			log.Printf("Could not accept server channel: %s", err.Error())
			return err
		}

		// connect requests
		go func() {
			log.Printf("Waiting for request")

		r:
			for {
				var req *ssh.Request
				var dst ssh.Channel

				select {
				case req = <-requests:
					dst = channel2
				case req = <-requests2:
					dst = channel
				}

				log.Printf("Request: %s %s %s %s\n", dst, req.Type, req.WantReply, req.Payload)

				b, err := dst.SendRequest(req.Type, req.WantReply, req.Payload)
				if err != nil {
					log.Printf("%s", err)
				}

				if req.WantReply {
					req.Reply(b, nil)
				}

				switch req.Type {
				case "exit-status":
					break r
				case "exec":
					// not supported (yet)
				default:
					log.Println(req.Type)
				}
			}

			channel.Close()
			channel2.Close()
		}()

		// connect channels
		log.Printf("Connecting channels.")

		var wrappedChannel io.ReadCloser = channel
		var wrappedChannel2 io.ReadCloser = channel2

		if p.wrapFn != nil {
			// wrappedChannel, err = p.wrapFn(channel)
			wrappedChannel2, err = p.wrapFn(serverConn, channel2)
		}

		go io.Copy(channel2, wrappedChannel)
		go io.Copy(channel, wrappedChannel2)

		defer wrappedChannel.Close()
		defer wrappedChannel2.Close()
	}

	if p.closeFn != nil {
		p.closeFn(serverConn)
	}

	return nil
}

func ListenAndServe(addr string, serverConfig *ssh.ServerConfig,
	callbackFn func(c ssh.ConnMetadata) (*ssh.Client, error),
	wrapFn func(c ssh.ConnMetadata, r io.ReadCloser) (io.ReadCloser, error),
	closeFn func(c ssh.ConnMetadata) error,
) {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Printf("net.Listen failed: %v", err)
		return err
	}

	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("listen.Accept failed: %v", err)
			return err
		}

		sshconn := &SshConn{Conn: conn, config: serverConfig, callbackFn: callbackFn, wrapFn: wrapFn, closeFn: closeFn}

		go func() {
			if err := sshconn.serve(); err != nil {
				log.Printf("Error occured while serving %s\n", err)
				return
			}

			log.Println("Connection closed.")
		}()
	}

}
<commit_msg>removed panics<commit_after>package sshproxy

import (
	"code.google.com/p/go.crypto/ssh"
	"io"
	"log"
	"net"
)

type SshConn struct {
	net.Conn
	config     *ssh.ServerConfig
	callbackFn func(c ssh.ConnMetadata) (*ssh.Client, error)
	wrapFn     func(c ssh.ConnMetadata, r io.ReadCloser) (io.ReadCloser, error)
	closeFn    func(c ssh.ConnMetadata) error
}

func (p *SshConn) serve() error {
	serverConn, chans, reqs, err := ssh.NewServerConn(p, p.config)
	if err != nil {
		log.Println("failed to handshake")
		return (err)
	}

	defer serverConn.Close()

	clientConn, err := p.callbackFn(serverConn)
	if err != nil {
		log.Printf("%s", err.Error())
		return (err)
	}

	defer clientConn.Close()

	go ssh.DiscardRequests(reqs)

	for newChannel := range chans {

		channel2, requests2, err2 := clientConn.OpenChannel(newChannel.ChannelType(), newChannel.ExtraData())
		if err2 != nil {
			log.Printf("Could not accept client channel: %s", err.Error())
			return err
		}

		channel, requests, err := newChannel.Accept()
		if err != nil {
			log.Printf("Could not accept server channel: %s", err.Error())
			return err
		}

		// connect requests
		go func() {
			log.Printf("Waiting for request")

		r:
			for {
				var req *ssh.Request
				var dst ssh.Channel

				select {
				case req = <-requests:
					dst = channel2
				case req = <-requests2:
					dst = channel
				}

				log.Printf("Request: %s %s %s %s\n", dst, req.Type, req.WantReply, req.Payload)

				b, err := dst.SendRequest(req.Type, req.WantReply, req.Payload)
				if err != nil {
					log.Printf("%s", err)
				}

				if req.WantReply {
					req.Reply(b, nil)
				}

				switch req.Type {
				case "exit-status":
					break r
				case "exec":
					// not supported (yet)
				default:
					log.Println(req.Type)
				}
			}

			channel.Close()
			channel2.Close()
		}()

		// connect channels
		log.Printf("Connecting channels.")

		var wrappedChannel io.ReadCloser = channel
		var wrappedChannel2 io.ReadCloser = channel2

		if p.wrapFn != nil {
			// wrappedChannel, err = p.wrapFn(channel)
			wrappedChannel2, err = p.wrapFn(serverConn, channel2)
		}

		go io.Copy(channel2, wrappedChannel)
		go io.Copy(channel, wrappedChannel2)

		defer wrappedChannel.Close()
		defer wrappedChannel2.Close()
	}

	if p.closeFn != nil {
		p.closeFn(serverConn)
	}

	return nil
}

func ListenAndServe(addr string, serverConfig *ssh.ServerConfig,
	callbackFn func(c ssh.ConnMetadata) (*ssh.Client, error),
	wrapFn func(c ssh.ConnMetadata, r io.ReadCloser) (io.ReadCloser, error),
	closeFn func(c ssh.ConnMetadata) error,
) error {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		log.Printf("net.Listen failed: %v", err)
		return err
	}

	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("listen.Accept failed: %v", err)
			return err
		}

		sshconn := &SshConn{Conn: conn, config: serverConfig, callbackFn: callbackFn, wrapFn: wrapFn, closeFn: closeFn}

		go func() {
			if err := sshconn.serve(); err != nil {
				log.Printf("Error occured while serving %s\n", err)
				return
			}

			log.Println("Connection closed.")
		}()
	}

}
<|endoftext|>


<commit_before>// 2d tile space direction
package direction

import (
	"github.com/kasworld/rand"
)

const (
	Dir_stop = iota
	Dir_n
	Dir_ne
	Dir_e
	Dir_se
	Dir_s
	Dir_sw
	Dir_w
	Dir_nw
)

var Dir2Info = []struct {
	Name string
	Vt   [2]int
	Len  float64
}{
	Dir_stop: {".", [2]int{0, 0}, 0.0},
	Dir_n:    {"N", [2]int{0, -1}, 1.0},
	Dir_ne:   {"NE", [2]int{1, -1}, 1.4},
	Dir_e:    {"E", [2]int{1, 0}, 1.0},
	Dir_se:   {"SE", [2]int{1, 1}, 1.4},
	Dir_s:    {"S", [2]int{0, 1}, 1.0},
	Dir_sw:   {"SW", [2]int{-1, 1}, 1.4},
	Dir_w:    {"W", [2]int{-1, 0}, 1.0},
	Dir_nw:   {"NW", [2]int{-1, -1}, 1.4},
}

var vt2Dir = [3][3]uint8{}

func init() {
	for i, v := range Dir2Info {
		vt2Dir[v.Vt[0]+1][v.Vt[1]+1] = uint8(i)
	}
}

func Vt2Dir(x, y int) uint8 { // -1 ~ 1
	return vt2Dir[x+1][y+1]
}
func VtValidate(x, y int) bool {
	return x >= -1 && x <= 1 && y >= -1 && y <= 1
}

func TurnDir(dir uint8, turn int8) uint8 {
	if dir == Dir_stop {
		return dir
	}
	turn %= 8
	return uint8((int8(dir)-1+turn+8)%8 + 1)
}
func ReverseDir(dir uint8) uint8 {
	vt := Dir2Info[dir].Vt
	return Vt2Dir(-vt[0], -vt[1])
}
func InverseX(dir uint8) uint8 {
	vt := Dir2Info[dir].Vt
	return Vt2Dir(-vt[0], vt[1])
}
func InverseY(dir uint8) uint8 {
	vt := Dir2Info[dir].Vt
	return Vt2Dir(vt[0], -vt[1])
}

func RandDir(rnd *rand.Rand) uint8 {
	return uint8(rnd.IntRange(1, 9))
}

/////

func GetSignAbs(n int) (int, int) {
	if n > 0 {
		return 1, n
	} else if n < 0 {
		return -1, -n
	} else {
		return 0, 0
	}
}

func DxDy2Dir8(dx, dy int) uint8 {
	dxs, dxv := GetSignAbs(dx)
	dys, dyv := GetSignAbs(dy)
	if dxv > dyv*2 {
		dys = 0
	}
	if dyv > dxv*2 {
		dxs = 0
	}
	return Vt2Dir(dxs, dys)
}

func DxDy2Dir4(dx, dy int) uint8 {
	dxs, dxv := GetSignAbs(dx)
	dys, dyv := GetSignAbs(dy)
	if dxv >= dyv {
		dys = 0
	} else {
		dxs = 0
	}
	return Vt2Dir(dxs, dys)
}
func DxDy2Dir(dx, dy int) uint8 {
	dxs, _ := GetSignAbs(dx)
	dys, _ := GetSignAbs(dy)
	return Vt2Dir(dxs, dys)
}
<commit_msg>change to use go-abs package<commit_after>// 2d tile space direction
package direction

import (
	"github.com/kasworld/go-abs"
	"github.com/kasworld/rand"
)

const (
	Dir_stop = iota
	Dir_n
	Dir_ne
	Dir_e
	Dir_se
	Dir_s
	Dir_sw
	Dir_w
	Dir_nw
)

var Dir2Info = []struct {
	Name string
	Vt   [2]int
	Len  float64
}{
	Dir_stop: {".", [2]int{0, 0}, 0.0},
	Dir_n:    {"N", [2]int{0, -1}, 1.0},
	Dir_ne:   {"NE", [2]int{1, -1}, 1.4},
	Dir_e:    {"E", [2]int{1, 0}, 1.0},
	Dir_se:   {"SE", [2]int{1, 1}, 1.4},
	Dir_s:    {"S", [2]int{0, 1}, 1.0},
	Dir_sw:   {"SW", [2]int{-1, 1}, 1.4},
	Dir_w:    {"W", [2]int{-1, 0}, 1.0},
	Dir_nw:   {"NW", [2]int{-1, -1}, 1.4},
}

var vt2Dir = [3][3]uint8{}

func init() {
	for i, v := range Dir2Info {
		vt2Dir[v.Vt[0]+1][v.Vt[1]+1] = uint8(i)
	}
}

func Vt2Dir(x, y int) uint8 { // -1 ~ 1
	return vt2Dir[x+1][y+1]
}
func VtValidate(x, y int) bool {
	return x >= -1 && x <= 1 && y >= -1 && y <= 1
}

func TurnDir(dir uint8, turn int8) uint8 {
	if dir == Dir_stop {
		return dir
	}
	turn %= 8
	return uint8((int8(dir)-1+turn+8)%8 + 1)
}
func ReverseDir(dir uint8) uint8 {
	vt := Dir2Info[dir].Vt
	return Vt2Dir(-vt[0], -vt[1])
}
func InverseX(dir uint8) uint8 {
	vt := Dir2Info[dir].Vt
	return Vt2Dir(-vt[0], vt[1])
}
func InverseY(dir uint8) uint8 {
	vt := Dir2Info[dir].Vt
	return Vt2Dir(vt[0], -vt[1])
}

func RandDir(rnd *rand.Rand) uint8 {
	return uint8(rnd.IntRange(1, 9))
}

/////

func DxDy2Dir8(dx, dy int) uint8 {
	dxs, dxv := abs.SignAbsi(dx)
	dys, dyv := abs.SignAbsi(dy)
	if dxv > dyv*2 {
		dys = 0
	}
	if dyv > dxv*2 {
		dxs = 0
	}
	return Vt2Dir(dxs, dys)
}

func DxDy2Dir4(dx, dy int) uint8 {
	dxs, dxv := abs.SignAbsi(dx)
	dys, dyv := abs.SignAbsi(dy)
	if dxv >= dyv {
		dys = 0
	} else {
		dxs = 0
	}
	return Vt2Dir(dxs, dys)
}
func DxDy2Dir(dx, dy int) uint8 {
	dxs, _ := abs.SignAbsi(dx)
	dys, _ := abs.SignAbsi(dy)
	return Vt2Dir(dxs, dys)
}
<|endoftext|>


<commit_before>package glob

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

type Dir interface {
	Glob(patterns ...string) (filePaths []string, err error)
}

type dir struct {
	path string
}

func NewDir(path string) (d Dir) {
	return dir{path: path}
}

func (d dir) Glob(patterns ...string) (filePaths []string, err error) {
	for _, pattern := range patterns {
		var newFiles []string

		newFiles, err = d.glob(pattern)
		if err != nil {
			err = wrapError(err, "Finding files matching pattern %s", pattern)
			return
		}

		filePaths = append(filePaths, newFiles...)
	}

	return
}

func (d dir) glob(pattern string) (files []string, err error) {
	globPattern := filepath.Join(d.path, pattern)

	glob, err := CompileGlob(globPattern)
	if err != nil {
		err = wrapError(err, "Compiling glob for pattern %s", pattern)
		return
	}

	filepath.Walk(d.path, func(path string, info os.FileInfo, inErr error) (err error) {
		if inErr != nil {
			err = inErr
			return
		}

		if glob.Match(path) {
			files = append(files, strings.Replace(path, d.path+"/", "", 1))
		}

		return
	})

	//	Ruby Dir.glob will include *.log when looking for **/*.log
	//	Our glob implementation will not do it automatically
	if strings.Contains(pattern, "**/*") {
		var extraFiles []string

		updatedPattern := strings.Replace(pattern, "**/*", "*", 1)
		extraFiles, err = d.glob(updatedPattern)
		if err != nil {
			err = wrapError(err, "Recursing into pattern %s", updatedPattern)
			return
		}

		files = append(files, extraFiles...)
	}
	return
}

func wrapError(err error, msg string, args ...interface{}) (newErr error) {
	msg = fmt.Sprintf(msg, args...)
	return errors.New(fmt.Sprintf("%s: %s", msg, err.Error()))
}
<commit_msg>Unify file paths when matching patterns in glob<commit_after>package glob

import (
	"errors"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
)

type Dir interface {
	Glob(patterns ...string) (filePaths []string, err error)
}

type dir struct {
	path string
}

func NewDir(path string) (d Dir) {
	return dir{path: path}
}

func (d dir) Glob(patterns ...string) (filePaths []string, err error) {
	for _, pattern := range patterns {
		var newFiles []string

		newFiles, err = d.glob(pattern)
		if err != nil {
			err = wrapError(err, "Finding files matching pattern %s", pattern)
			return
		}

		filePaths = append(filePaths, newFiles...)
	}

	return
}

func (d dir) glob(pattern string) (files []string, err error) {
	// unify path so that pattern will match files on Windows
	unifiedPath := strings.TrimPrefix(filepath.ToSlash(d.path), filepath.VolumeName(d.path))
	globPattern := path.Join(unifiedPath, pattern)

	glob, err := CompileGlob(globPattern)
	if err != nil {
		err = wrapError(err, "Compiling glob for pattern %s", pattern)
		return
	}

	filepath.Walk(d.path, func(path string, info os.FileInfo, inErr error) (err error) {
		path = strings.TrimPrefix(filepath.ToSlash(path), filepath.VolumeName(path))

		if inErr != nil {
			err = inErr
			return
		}

		if glob.Match(path) {
			files = append(files, strings.Replace(path, unifiedPath+"/", "", 1))
		}

		return
	})

	//	Ruby Dir.glob will include *.log when looking for **/*.log
	//	Our glob implementation will not do it automatically
	if strings.Contains(pattern, "**/*") {
		var extraFiles []string

		updatedPattern := strings.Replace(pattern, "**/*", "*", 1)
		extraFiles, err = d.glob(updatedPattern)
		if err != nil {
			err = wrapError(err, "Recursing into pattern %s", updatedPattern)
			return
		}

		files = append(files, extraFiles...)
	}
	return
}

func wrapError(err error, msg string, args ...interface{}) (newErr error) {
	msg = fmt.Sprintf(msg, args...)
	return errors.New(fmt.Sprintf("%s: %s", msg, err.Error()))
}
<|endoftext|>


<commit_before>package server
// import (
// 	"testing"
//
// 	"github.com/wanelo/image-server/core"
// )
//
// func TestAllowedImageValid(t *testing.T) {
// 	fmts := []string{"jpg"}
// 	sc := &core.ServerConfiguration{MaximumWidth: 1000, WhitelistedExtensions: fmts}
// 	ic := &core.ImageConfiguration{ServerConfiguration: sc, Width: 1000, Format: "jpg"}
//
// 	allowed, _ := allowedImage(ic)
// 	if allowed == false {
// 		t.Errorf("expected true")
// 	}
// }
//
// func TestAllowedImageTooWide(t *testing.T) {
// 	fmts := []string{"jpg"}
// 	sc := &core.ServerConfiguration{MaximumWidth: 1000, WhitelistedExtensions: fmts}
// 	ic := &core.ImageConfiguration{ServerConfiguration: sc, Width: 1001, Format: "jpg"}
//
// 	allowed, _ := allowedImage(ic)
// 	if allowed == true {
// 		t.Errorf("expected false")
// 	}
// }
//
// func TestAllowedImageInvalidFormat(t *testing.T) {
// 	fmts := []string{"jpg"}
// 	sc := &core.ServerConfiguration{MaximumWidth: 1000, WhitelistedExtensions: fmts}
// 	ic := &core.ImageConfiguration{ServerConfiguration: sc, Width: 100, Format: "pdf"}
//
// 	allowed, _ := allowedImage(ic)
// 	if allowed == true {
// 		t.Errorf("expected false")
// 	}
// }
<commit_msg>go fmt handlers_test.go<commit_after>package server

// import (
// 	"testing"
//
// 	"github.com/wanelo/image-server/core"
// )
//
// func TestAllowedImageValid(t *testing.T) {
// 	fmts := []string{"jpg"}
// 	sc := &core.ServerConfiguration{MaximumWidth: 1000, WhitelistedExtensions: fmts}
// 	ic := &core.ImageConfiguration{ServerConfiguration: sc, Width: 1000, Format: "jpg"}
//
// 	allowed, _ := allowedImage(ic)
// 	if allowed == false {
// 		t.Errorf("expected true")
// 	}
// }
//
// func TestAllowedImageTooWide(t *testing.T) {
// 	fmts := []string{"jpg"}
// 	sc := &core.ServerConfiguration{MaximumWidth: 1000, WhitelistedExtensions: fmts}
// 	ic := &core.ImageConfiguration{ServerConfiguration: sc, Width: 1001, Format: "jpg"}
//
// 	allowed, _ := allowedImage(ic)
// 	if allowed == true {
// 		t.Errorf("expected false")
// 	}
// }
//
// func TestAllowedImageInvalidFormat(t *testing.T) {
// 	fmts := []string{"jpg"}
// 	sc := &core.ServerConfiguration{MaximumWidth: 1000, WhitelistedExtensions: fmts}
// 	ic := &core.ImageConfiguration{ServerConfiguration: sc, Width: 100, Format: "pdf"}
//
// 	allowed, _ := allowedImage(ic)
// 	if allowed == true {
// 		t.Errorf("expected false")
// 	}
// }
<|endoftext|>


<commit_before>package logger

import (
	"os"

	"github.com/uber-go/zap"
)

var (
	AccessLogger = zap.New(zap.NewJSONEncoder(), zap.Output(os.Stdout))
	AppLogger    = zap.New(zap.NewJSONEncoder(), zap.Output(os.Stderr))
)
<commit_msg>Change log timestamp format<commit_after>package logger

import (
	"os"

	"github.com/uber-go/zap"
)

var (
	AccessLogger = zap.New(zap.NewJSONEncoder(zap.RFC3339Formatter("ts")), zap.Output(os.Stdout))
	AppLogger    = zap.New(zap.NewJSONEncoder(zap.RFC3339Formatter("ts")), zap.Output(os.Stderr))
)
<|endoftext|>


<commit_before>package thermal

import (
	//"code.google.com/p/go.crypto/nacl/secretbox"
	"code.google.com/p/go.crypto/nacl/box"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
	"log"
)

// cs3a is an implementation of the NaCl based cipher set 3a
type cs3a struct {
	id             string
	fingerprintBin []byte
	fingerprintHex string
	publicKey      [32]byte
	privateKey     [32]byte
}

// initialize generates a key pair and sets up the cipher set
func (cs *cs3a) initialize() error {

	// generate the key pair
	publicKey, privateKey, err := box.GenerateKey(rand.Reader)
	if err != nil {
		log.Println("Error generating NaCl keypair in cs3a initialization")
		return err
	}

	// generate the fingerprint hash
	hash256 := sha256.New()
	hash256.Write(publicKey[:])
	fingerprintBin := hash256.Sum(nil)
	fingerprintHex := fmt.Sprintf("%x", fingerprintBin)

	// initialize the struct
	cs.id = "cs3a"
	cs.fingerprintBin = fingerprintBin
	cs.fingerprintHex = fingerprintHex
	cs.publicKey = *publicKey
	cs.privateKey = *privateKey

	return nil

}

func (cs *cs3a) String() string {
	return fmt.Sprintf("%s: %x", cs.id, cs.fingerprint)
}

func (cs *cs3a) csid() string {
	return cs.id
}

// fingerprint returns the csid and fingerprint for use in a 'parts' set
func (cs *cs3a) fingerprint() (string, string) {
	return cs.id, cs.fingerprintHex
}

func (cs *cs3a) encryptOpenPacket(packet []byte) csdata []byte {

	//------------------------------------------------------
	// Setup the keys
	//------------------------------------------------------
	// . existing switch key pair
	// . new line key pair?	// return?  store in local map?

	//------------------------------------------------------
	// Encrypt the inner packet
	//------------------------------------------------------
	// . 24 byte nonce of 0
	// nonce = make([]byte, 24)

	// . generate the shared secret
	// crypto_box(agreedKey, receiver.pubkey, sender.line.prvkey)

	// . use secretbox to encrypt the inner packet
	// encInnerPacket = crypto_secretbox(data, nonce, agreedKey)

	//------------------------------------------------------
	// Generate the hmac and assemble the outer packet
	//------------------------------------------------------
	// . <open-HMAC><sender-line-public-key><encrypted-inner-packet-data>
	// .		csdata.00-32  == auth - onetimeauth
	// .		csdata.33-64  == line_key - senders line level public key
	// .		csdata.rest   == inner_ciphertext (encrypted open packet)

	// . assemble part of the outer packet
	// outerPacketData = sender_linekey.public + encInnerPacket

	// . generate the macKey for use in generating the hmac
	// crypto_box(macKey, receiver.pubkey, sender.prvkey)

	// . generate the hmac
	// hmac = crypto_onetimeauth(encInnerPacket, macKey)
	// var hmac
	// crypt.poly1305.sum(hmac, encInnerPacket, macKey)

	// . assemble the rest of the outer packet BODY
	// csdata = hmac + outerPacketData
	//

}

func (cs *cs3a) decryptOpenPacket(csdata []byte) packet []byte {}

func (cs *cs3a) encryptLinePacket(packet []byte) csdata []byte {}

func (cs *cs3a) decryptLinePacket(csdata []byte) packet []byte {}
<commit_msg>add return to skeleton functions<commit_after>package thermal

import (
	//"code.google.com/p/go.crypto/nacl/secretbox"
	"code.google.com/p/go.crypto/nacl/box"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
	"log"
)

// cs3a is an implementation of the NaCl based cipher set 3a
type cs3a struct {
	id             string
	fingerprintBin []byte
	fingerprintHex string
	publicKey      [32]byte
	privateKey     [32]byte
}

// initialize generates a key pair and sets up the cipher set
func (cs *cs3a) initialize() error {

	// generate the key pair
	publicKey, privateKey, err := box.GenerateKey(rand.Reader)
	if err != nil {
		log.Println("Error generating NaCl keypair in cs3a initialization")
		return err
	}

	// generate the fingerprint hash
	hash256 := sha256.New()
	hash256.Write(publicKey[:])
	fingerprintBin := hash256.Sum(nil)
	fingerprintHex := fmt.Sprintf("%x", fingerprintBin)

	// initialize the struct
	cs.id = "cs3a"
	cs.fingerprintBin = fingerprintBin
	cs.fingerprintHex = fingerprintHex
	cs.publicKey = *publicKey
	cs.privateKey = *privateKey

	return nil

}

func (cs *cs3a) String() string {
	return fmt.Sprintf("%s: %x", cs.id, cs.fingerprint)
}

func (cs *cs3a) csid() string {
	return cs.id
}

// fingerprint returns the csid and fingerprint for use in a 'parts' set
func (cs *cs3a) fingerprint() (string, string) {
	return cs.id, cs.fingerprintHex
}

func (cs *cs3a) encryptOpenPacket(packet []byte) (csdata []byte) {

	//------------------------------------------------------
	// Setup the keys
	//------------------------------------------------------
	// . existing switch key pair
	// . new line key pair?	// return?  store in local map?

	//------------------------------------------------------
	// Encrypt the inner packet
	//------------------------------------------------------
	// . 24 byte nonce of 0
	// nonce = make([]byte, 24)

	// . generate the shared secret
	// crypto_box(agreedKey, receiver.pubkey, sender.line.prvkey)

	// . use secretbox to encrypt the inner packet
	// encInnerPacket = crypto_secretbox(data, nonce, agreedKey)

	//------------------------------------------------------
	// Generate the hmac and assemble the outer packet
	//------------------------------------------------------
	// . <open-HMAC><sender-line-public-key><encrypted-inner-packet-data>
	// .		csdata.00-32  == auth - onetimeauth
	// .		csdata.33-64  == line_key - senders line level public key
	// .		csdata.rest   == inner_ciphertext (encrypted open packet)

	// . assemble part of the outer packet
	// outerPacketData = sender_linekey.public + encInnerPacket

	// . generate the macKey for use in generating the hmac
	// crypto_box(macKey, receiver.pubkey, sender.prvkey)

	// . generate the hmac
	// hmac = crypto_onetimeauth(encInnerPacket, macKey)
	// var hmac
	// crypt.poly1305.sum(hmac, encInnerPacket, macKey)

	// . assemble the rest of the outer packet BODY
	// csdata = hmac + outerPacketData
	//
	return csdata

}

func (cs *cs3a) decryptOpenPacket(csdata []byte) (packet []byte) {
	return packet
}

func (cs *cs3a) encryptLinePacket(packet []byte) (csdata []byte) {
	return csdata
}

func (cs *cs3a) decryptLinePacket(csdata []byte) (packet []byte) {
	return packet
}
<|endoftext|>


<commit_before>package bot

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"

	"github.com/belak/irc"
	"github.com/khades/servbot/commandHandlers"
	"github.com/khades/servbot/ircClient"
	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message) {
	//	log.Println(message.String())
	msgID, found := message.Tags.GetTag("msg-id")
	if found {
		switch msgID {
		case "room_mods":
			{
				commaIndex := strings.Index(message.Params[1], ":")
				if commaIndex != -1 {
					//				log.Printf("Channel %v: got mods list", message.Params[0])
					mods := strings.Split(message.Params[1][commaIndex+2:], ", ")
					repos.PushMods(message.Params[0][1:], mods)
				}
			}
		case "resub":
			{
				msgParamMonths, msgParamMonthsFound := message.Tags.GetTag("msg-param-months")
				user, userFound := message.Tags.GetTag("display-name")
				channel := message.Params[0]
				if msgParamMonthsFound && userFound && channel != "" {
					resubCount, resubCountError := strconv.Atoi(msgParamMonths)
					if resubCountError == nil {
						formedMessage := models.ChatMessage{
							Channel:          channel,
							User:             user,
							IsMod:            false,
							IsSub:            true,
							Date:             time.Now(),
							SubscriptionInfo: &models.SubscriptionInfo{Count: resubCount}}
						repos.LogMessage(formedMessage)
						channelInfo, error := repos.GetChannelInfo(channel)
						if error == nil && channelInfo.SubAlert.Enabled == true {
							messageBody := strings.TrimSpace(fmt.Sprintf("%s %s%s",
								channelInfo.SubAlert.RepeatPrefix,
								strings.Repeat(channelInfo.SubAlert.RepeatBody+" ", formedMessage.SubscriptionInfo.Count),
								channelInfo.SubAlert.RepeatPostfix))
							if messageBody != "" {
								IrcClientInstance.SendPublic(models.OutgoingMessage{
									Body:    messageBody,
									Channel: channel,
									User:    user})
							}
						}
						log.Printf("Channel %v: %v resubbed for %v months\n", formedMessage.Channel, formedMessage.User, formedMessage.SubscriptionInfo.Count)
					}
				}
			}
		}
	}

	if message.User == "twitchnotify" {
		log.Println("Got first sub")
		user, userFound := message.Tags.GetTag("display-name")
		log.Println(message.Tags.String())
		channel := message.Params[0]
		log.Println(user)
		log.Println(channel)

		if userFound && channel != "" {
			formedMessage := models.ChatMessage{
				Channel:          channel,
				User:             user,
				IsMod:            false,
				IsSub:            true,
				IsPrime:          strings.Contains(message.String(), "Twitch Prime"),
				Date:             time.Now(),
				SubscriptionInfo: &models.SubscriptionInfo{Count: 1}}
			repos.LogMessage(formedMessage)
			channelInfo, error := repos.GetChannelInfo(channel)
			if error == nil && channelInfo.SubAlert.Enabled == true && channelInfo.SubAlert.FirstMessage != "" {
				IrcClientInstance.SendPublic(models.OutgoingMessage{
					Body:    channelInfo.SubAlert.FirstMessage,
					Channel: channel,
					User:    user})
			}
			log.Printf("Channel %v: %v subbed\n", formedMessage.Channel, formedMessage.User)
		}
	}
	if message.Command == "CLEARCHAT" {
		banDuration, banDurationFound := message.Tags.GetTag("ban-duration")
		intBanDuration := 0
		if banDurationFound {
			parsedValue, parseError := strconv.Atoi(banDuration)
			if parseError == nil {
				intBanDuration = parsedValue
			}
		}
		banReason, _ := message.Tags.GetTag("ban-reason")
		user := message.Params[1]
		channel := message.Params[0]
		formedMessage := models.ChatMessage{
			Channel: channel,
			User:    user,
			IsMod:   false,
			IsSub:   true,
			Date:    time.Now(),
			BanInfo: &models.BanInfo{Duration: intBanDuration, Reason: banReason}}
		repos.LogMessage(formedMessage)
		//	log.Printf("Channel %v: %v is banned for %v \n", channel, user, intBanDuration)
	}
	if message.Command == "PRIVMSG" {
		formedMessage := models.ChatMessage{
			Channel:     message.Params[0][1:],
			User:        message.User,
			MessageBody: message.Params[1],
			IsMod:       message.Tags["mod"] == "1" || message.User == "khadesru",
			IsSub:       message.Tags["subscriber"] == "1",
			IsPrime:     strings.Contains(message.Tags["badges"].Encode(), "premium/1"),
			Date:        time.Now()}
		repos.LogMessage(formedMessage)
		isCommand, commandBody := formedMessage.IsCommand()
		if isCommand {
			handlerFunction := commandHandlers.Router.Go(commandBody.Command)
			handlerFunction(true, &formedMessage, commandBody, &IrcClientInstance)
		}
	}

	if message.Command == "001" {
		client.Write("CAP REQ twitch.tv/tags")
		client.Write("CAP REQ twitch.tv/membership")
		client.Write("CAP REQ twitch.tv/commands")
		for _, value := range repos.Config.Channels {
			client.Write("JOIN #" + value)
		}
		IrcClientInstance = ircClient.IrcClient{Client: client, Bounces: make(map[string]time.Time), Ready: true}
		IrcClientInstance.SendModsCommand()
		log.Println("Bot is started")
	}
}
<commit_msg>Fixing subalert<commit_after>package bot

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"

	"github.com/belak/irc"
	"github.com/khades/servbot/commandHandlers"
	"github.com/khades/servbot/ircClient"
	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message) {
	//	log.Println(message.String())
	msgID, found := message.Tags.GetTag("msg-id")
	if found {
		switch msgID {
		case "room_mods":
			{
				commaIndex := strings.Index(message.Params[1], ":")
				if commaIndex != -1 {
					//				log.Printf("Channel %v: got mods list", message.Params[0])
					mods := strings.Split(message.Params[1][commaIndex+2:], ", ")
					repos.PushMods(message.Params[0][1:], mods)
				}
			}
		case "resub":
			{
				msgParamMonths, msgParamMonthsFound := message.Tags.GetTag("msg-param-months")
				user, userFound := message.Tags.GetTag("display-name")
				channel := message.Params[0]
				if msgParamMonthsFound && userFound && channel != "" {
					resubCount, resubCountError := strconv.Atoi(msgParamMonths)
					if resubCountError == nil {
						formedMessage := models.ChatMessage{
							Channel:          channel,
							User:             user,
							IsMod:            false,
							IsSub:            true,
							Date:             time.Now(),
							SubscriptionInfo: &models.SubscriptionInfo{Count: resubCount}}
						repos.LogMessage(formedMessage)
						channelInfo, error := repos.GetChannelInfo(channel)
						if error == nil && channelInfo.SubAlert.Enabled == true {
							messageBody := strings.TrimSpace(fmt.Sprintf("%s %s%s",
								channelInfo.SubAlert.RepeatPrefix,
								strings.Repeat(channelInfo.SubAlert.RepeatBody+" ", formedMessage.SubscriptionInfo.Count),
								channelInfo.SubAlert.RepeatPostfix))
							if messageBody != "" {
								IrcClientInstance.SendPublic(models.OutgoingMessage{
									Body:    messageBody,
									Channel: channel,
									User:    user})
							}
						}
						log.Printf("Channel %v: %v resubbed for %v months\n", formedMessage.Channel, formedMessage.User, formedMessage.SubscriptionInfo.Count)
					}
				}
			}
		}
	}

	if message.User == "twitchnotify" {
		log.Println("Got first sub")
		user := strings.Split(message.Params[1], " ")[0]
		channel := message.Params[0]
		log.Println(user)
		log.Println(channel)

		if user != "" && channel != "" {
			formedMessage := models.ChatMessage{
				Channel:          channel,
				User:             user,
				IsMod:            false,
				IsSub:            true,
				IsPrime:          strings.Contains(message.String(), "Twitch Prime"),
				Date:             time.Now(),
				SubscriptionInfo: &models.SubscriptionInfo{Count: 1}}
			repos.LogMessage(formedMessage)
			channelInfo, error := repos.GetChannelInfo(channel)
			if error == nil && channelInfo.SubAlert.Enabled == true && channelInfo.SubAlert.FirstMessage != "" {
				IrcClientInstance.SendPublic(models.OutgoingMessage{
					Body:    channelInfo.SubAlert.FirstMessage,
					Channel: channel,
					User:    user})
			}
			log.Printf("Channel %v: %v subbed\n", formedMessage.Channel, formedMessage.User)
		}
	}
	if message.Command == "CLEARCHAT" {
		banDuration, banDurationFound := message.Tags.GetTag("ban-duration")
		intBanDuration := 0
		if banDurationFound {
			parsedValue, parseError := strconv.Atoi(banDuration)
			if parseError == nil {
				intBanDuration = parsedValue
			}
		}
		banReason, _ := message.Tags.GetTag("ban-reason")
		user := message.Params[1]
		channel := message.Params[0]
		formedMessage := models.ChatMessage{
			Channel: channel,
			User:    user,
			IsMod:   false,
			IsSub:   true,
			Date:    time.Now(),
			BanInfo: &models.BanInfo{Duration: intBanDuration, Reason: banReason}}
		repos.LogMessage(formedMessage)
		//	log.Printf("Channel %v: %v is banned for %v \n", channel, user, intBanDuration)
	}
	if message.Command == "PRIVMSG" {
		formedMessage := models.ChatMessage{
			Channel:     message.Params[0][1:],
			User:        message.User,
			MessageBody: message.Params[1],
			IsMod:       message.Tags["mod"] == "1" || message.User == "khadesru",
			IsSub:       message.Tags["subscriber"] == "1",
			IsPrime:     strings.Contains(message.Tags["badges"].Encode(), "premium/1"),
			Date:        time.Now()}
		repos.LogMessage(formedMessage)
		isCommand, commandBody := formedMessage.IsCommand()
		if isCommand {
			handlerFunction := commandHandlers.Router.Go(commandBody.Command)
			handlerFunction(true, &formedMessage, commandBody, &IrcClientInstance)
		}
	}

	if message.Command == "001" {
		client.Write("CAP REQ twitch.tv/tags")
		client.Write("CAP REQ twitch.tv/membership")
		client.Write("CAP REQ twitch.tv/commands")
		for _, value := range repos.Config.Channels {
			client.Write("JOIN #" + value)
		}
		IrcClientInstance = ircClient.IrcClient{Client: client, Bounces: make(map[string]time.Time), Ready: true}
		IrcClientInstance.SendModsCommand()
		log.Println("Bot is started")
	}
}
<|endoftext|>