<commit_before>// Licensed to The Moov Authors under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. The Moov Authors licenses this file to you 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 ach

// Version Number
const Version = "v1.4.0-rc1"
<commit_msg>release v1.4.0-rc2<commit_after>// Licensed to The Moov Authors under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. The Moov Authors licenses this file to you 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 ach

// Version Number
const Version = "v1.4.0-rc2"
<|endoftext|>


<commit_before>package main

import "fmt"

type version struct {
	Major, Minor, Patch int
	Label               string
	Nick                string
}

var ver = version{
	Major: 1,
	Minor: 0,
	Patch: 0,
	Label: ""}

// CommitHash may be set on the build command line:
// go build -ldflags "-X main.CommitHash=`git rev-parse --short HEAD`"
var CommitHash string

const appName string = "dcrdata"

func (v *version) String() string {
	var hashStr string
	if CommitHash != "" {
		hashStr = "+" + CommitHash
	}
	if v.Label != "" {
		return fmt.Sprintf("%d.%d.%d-%s%s",
			v.Major, v.Minor, v.Patch, v.Label, hashStr)
	}
	return fmt.Sprintf("%d.%d.%d%s",
		v.Major, v.Minor, v.Patch, hashStr)
}
<commit_msg>bump version to 1.0.1<commit_after>package main

import "fmt"

type version struct {
	Major, Minor, Patch int
	Label               string
	Nick                string
}

var ver = version{
	Major: 1,
	Minor: 0,
	Patch: 1,
	Label: ""}

// CommitHash may be set on the build command line:
// go build -ldflags "-X main.CommitHash=`git rev-parse --short HEAD`"
var CommitHash string

const appName string = "dcrdata"

func (v *version) String() string {
	var hashStr string
	if CommitHash != "" {
		hashStr = "+" + CommitHash
	}
	if v.Label != "" {
		return fmt.Sprintf("%d.%d.%d-%s%s",
			v.Major, v.Minor, v.Patch, v.Label, hashStr)
	}
	return fmt.Sprintf("%d.%d.%d%s",
		v.Major, v.Minor, v.Patch, hashStr)
}
<|endoftext|>


<commit_before>package mailgun

// Version of current release
const Version = "4.5.3"
<commit_msg>Bump version<commit_after>package mailgun

// Version of current release
const Version = "4.6.0"
<|endoftext|>


<commit_before>package via

import (
	"github.com/ipfs/go-ipfs-api"
	"os"
)

func IpfsAdd(path Path) (string, error) {
	s := shell.NewLocalShell()
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return s.Add(fd)
}

func HashOnly(path Path) (string, error) {
	s := shell.NewLocalShell()
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return s.Add(fd, shell.OnlyHash(true))
}
<commit_msg>Revert "use go-ipfs-api for hashing"<commit_after>package via

import (
	"context"
	"github.com/ipfs/go-ipfs-api"
	"github.com/ipfs/go-ipfs/core"
	"github.com/ipfs/go-ipfs/core/coreunix"
	"os"
)

func IpfsAdd(path Path) (string, error) {
	s := shell.NewLocalShell()
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return s.Add(fd)
}

func HashOnly(path Path) (string, error) {
	node, err := core.NewNode(context.TODO(), &core.BuildCfg{NilRepo: true})
	if err != nil {
		return "", err
	}
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return coreunix.Add(node, fd)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Mute Communications Ltd.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package encdb defines an encrypted database used within Mute.
Such an encrypted database consists of two file for a given database file with
name "dbname":

  dbname.db
  dbname.key

The file "dbname.db" is an AES-256 encrypted sqlite3 file managed by the
package "mute/go-sqlcipher". The file named "dbname.key" is an
AES-256 encrypted text file which contains the (randomly generated) raw
encryption key for "dbname.db". To decrypt the key file the key derivation
function PBKDF2 is applied to a supplied passphrase (with a configurable number
of iterations) and the derived key is used as the AES-256 key for "dbname.key".

This design allows a very cheap rekey of the database, because only the key
file needs to be changed and the database file itself doesn't have to be
modified for a rekey operation.
*/
package encdb

import (
	"database/sql"
	"encoding/hex"
	"fmt"
	"os"

	_ "github.com/mutecomm/go-sqlcipher" // encDB is tightly coupled to go-sqlcipher
	"github.com/mutecomm/mute/log"
	"github.com/mutecomm/mute/util"
)

const (
	dbsuffix  = ".db"
	keysuffix = ".key"
)

func createTables(db *sql.DB, createStmts []string) error {
	for _, stmt := range createStmts {
		_, err := db.Exec(stmt)
		if err != nil {
			return log.Errorf("encdb: %q: %s", err, stmt)
		}
	}
	return nil
}

// Create tries to create an encrypted database with the given passphrase and
// iter many KDF iterations. Thereby, dbname is the prefix of the following
// two database files which will be created and must not exist already:
//
//  dbname.db
//  dbname.key
//
// The SQL database is initialized with the statements given in createStmts.
// In case of error (for example, the database files do exist already or
// cannot be created) an error is returned.
func Create(dbname string, passphrase []byte, iter int, createStmts []string) error {
	dbfile := dbname + dbsuffix
	keyfile := dbname + keysuffix
	// make sure files do not exist already
	if _, err := os.Stat(dbfile); err == nil {
		return log.Errorf("encdb: dbfile '%s' exists already", dbfile)
	}
	if _, err := os.Stat(keyfile); err == nil {
		return log.Errorf("encdb: dbfile '%s' exists already", keyfile)
	}
	// create keyfile
	key, err := generateKeyfile(keyfile, passphrase, iter)
	if err != nil {
		return err
	}
	// create DB
	dbfile += fmt.Sprintf("?_pragma_key=x'%s'&_pragma_cipher_page_size=4096",
		hex.EncodeToString(key))
	db, err := sql.Open("sqlite3", dbfile)
	if err != nil {
		return log.Error(err)
	}
	defer db.Close()
	_, err = db.Exec("PRAGMA auto_vacuum = full;")
	if err != nil {
		return log.Error(err)
	}
	return createTables(db, createStmts)
}

// Open tries to open an encrypted database with the given passphrase.
// Thereby, dbname is the prefix of the following two database files (which
// must already exist):
//
//  dbname.db
//  dbname.key
//
// In case of error (for example, the database files do not exist or the
// passphrase is wrong) an error is returned.
func Open(dbname string, passphrase []byte) (*sql.DB, error) {
	dbfile := dbname + dbsuffix
	keyfile := dbname + keysuffix
	// make sure files exists
	if _, err := os.Stat(dbfile); err != nil {
		return nil, log.Error(err)
	}
	if _, err := os.Stat(keyfile); err != nil {
		return nil, log.Error(err)
	}
	// get key from keyfile
	key, err := readKeyfile(keyfile, passphrase)
	if err != nil {
		return nil, err
	}
	// open DB
	dbfile += fmt.Sprintf("?_pragma_key=x'%s'&_pragma_cipher_page_size=4096",
		hex.EncodeToString(key))
	// enable foreign key support
	dbfile += "&_pragma_foreign_keys=on"
	db, err := sql.Open("sqlite3", dbfile)
	if err != nil {
		return nil, log.Error(err)
	}
	// test key
	_, err = db.Exec("SELECT count(*) FROM sqlite_master;")
	if err != nil {
		return nil, log.Error(err)
	}
	return db, nil
}

// Rekey tries to rekey an encrypted database with the given newPassphrase and
// newIter many KDF iterations. The correct oldPassphrase must be supplied.
// Thereby, dbname is the prefix of the following two database files (which must
// already exist):
//
//  dbname.db
//  dbname.key
//
// Rekey replaces the dbname.key file and leaves the dbname.db file unmodified,
// allowing for very fast rekey operations. In case of error (for example, the
// database files do not exist or the oldPassphrase is wrong) an error is
// returned.
func Rekey(dbname string, oldPassphrase, newPassphrase []byte, newIter int) error {
	encdb, err := Open(dbname, oldPassphrase)
	if err != nil {
		return err
	}
	defer encdb.Close()
	keyfile := dbname + keysuffix
	return replaceKeyfile(keyfile, oldPassphrase, newPassphrase, newIter)
}

var autoVacuumModes = []string{
	"NONE",
	"FULL",
	"INCREMENTAL",
}

// Status returns the autoVacuum and freelistCount of db.
func Status(db *sql.DB) (autoVacuum string, freelistCount int64, err error) {
	var av int64
	err = db.QueryRow("PRAGMA auto_vacuum;").Scan(&av)
	if err != nil {
		return "", 0, err
	}
	autoVacuum = autoVacuumModes[av]
	err = db.QueryRow("PRAGMA freelist_count;").Scan(&freelistCount)
	if err != nil {
		return "", 0, err
	}
	return
}

// Vacuum executes VACUUM command in db. If autoVacuumMode is not nil and
// different from the current one, the auto_vacuum mode is changed before
// VACUUM is executed.
func Vacuum(db *sql.DB, autoVacuumMode string) error {
	if autoVacuumMode != "" {
		if !util.ContainsString(autoVacuumModes, autoVacuumMode) {
			return log.Errorf("encdb: unknown auto_vacuum mode: %s", autoVacuumMode)
		}
		var av int64
		err := db.QueryRow("PRAGMA auto_vacuum;").Scan(&av)
		if err != nil {
			return err
		}
		currentMode := autoVacuumModes[av]
		if currentMode != autoVacuumMode {
			_, err = db.Exec(fmt.Sprintf("PRAGMA auto_vacuum = %s;", autoVacuumMode))
			if err != nil {
				return err
			}
		}
	}
	_, err := db.Exec("VACUUM;")
	if err != nil {
		return log.Error(err)
	}
	return nil
}

// Incremental executes incremental_vacuum to free up to pages many pages. If
// pages is 0, all pages are freed. If the current auto_vacuum mode is not
// INCREMENTAL, an error is returned.
func Incremental(db *sql.DB, pages int64) error {
	var av int64
	err := db.QueryRow("PRAGMA auto_vacuum;").Scan(&av)
	if err != nil {
		return err
	}
	if autoVacuumModes[av] != "INCREMENTAL" {
		return log.Error("encdb: current auto_vacuum mode is not INCREMENTAL")
	}
	_, err = db.Exec(fmt.Sprintf("PRAGMA incremental_vacuum(%d);", pages))
	if err != nil {
		log.Error(err)
	}
	return nil
}
<commit_msg>encdb: export file suffix constants<commit_after>// Copyright (c) 2015 Mute Communications Ltd.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package encdb defines an encrypted database used within Mute.
Such an encrypted database consists of two file for a given database file with
name "dbname":

  dbname.db
  dbname.key

The file "dbname.db" is an AES-256 encrypted sqlite3 file managed by the
package "mute/go-sqlcipher". The file named "dbname.key" is an
AES-256 encrypted text file which contains the (randomly generated) raw
encryption key for "dbname.db". To decrypt the key file the key derivation
function PBKDF2 is applied to a supplied passphrase (with a configurable number
of iterations) and the derived key is used as the AES-256 key for "dbname.key".

This design allows a very cheap rekey of the database, because only the key
file needs to be changed and the database file itself doesn't have to be
modified for a rekey operation.
*/
package encdb

import (
	"database/sql"
	"encoding/hex"
	"fmt"
	"os"

	_ "github.com/mutecomm/go-sqlcipher" // encDB is tightly coupled to go-sqlcipher
	"github.com/mutecomm/mute/log"
	"github.com/mutecomm/mute/util"
)

// DBSuffix defines the suffix for database files.
const DBSuffix = ".db"

// KeySuffix defines the suffix for key files.
const KeySuffix = ".key"

func createTables(db *sql.DB, createStmts []string) error {
	for _, stmt := range createStmts {
		_, err := db.Exec(stmt)
		if err != nil {
			return log.Errorf("encdb: %q: %s", err, stmt)
		}
	}
	return nil
}

// Create tries to create an encrypted database with the given passphrase and
// iter many KDF iterations. Thereby, dbname is the prefix of the following
// two database files which will be created and must not exist already:
//
//  dbname.db
//  dbname.key
//
// The SQL database is initialized with the statements given in createStmts.
// In case of error (for example, the database files do exist already or
// cannot be created) an error is returned.
func Create(dbname string, passphrase []byte, iter int, createStmts []string) error {
	dbfile := dbname + DBSuffix
	keyfile := dbname + KeySuffix
	// make sure files do not exist already
	if _, err := os.Stat(dbfile); err == nil {
		return log.Errorf("encdb: dbfile '%s' exists already", dbfile)
	}
	if _, err := os.Stat(keyfile); err == nil {
		return log.Errorf("encdb: dbfile '%s' exists already", keyfile)
	}
	// create keyfile
	key, err := generateKeyfile(keyfile, passphrase, iter)
	if err != nil {
		return err
	}
	// create DB
	dbfile += fmt.Sprintf("?_pragma_key=x'%s'&_pragma_cipher_page_size=4096",
		hex.EncodeToString(key))
	db, err := sql.Open("sqlite3", dbfile)
	if err != nil {
		return log.Error(err)
	}
	defer db.Close()
	_, err = db.Exec("PRAGMA auto_vacuum = full;")
	if err != nil {
		return log.Error(err)
	}
	return createTables(db, createStmts)
}

// Open tries to open an encrypted database with the given passphrase.
// Thereby, dbname is the prefix of the following two database files (which
// must already exist):
//
//  dbname.db
//  dbname.key
//
// In case of error (for example, the database files do not exist or the
// passphrase is wrong) an error is returned.
func Open(dbname string, passphrase []byte) (*sql.DB, error) {
	dbfile := dbname + DBSuffix
	keyfile := dbname + KeySuffix
	// make sure files exists
	if _, err := os.Stat(dbfile); err != nil {
		return nil, log.Error(err)
	}
	if _, err := os.Stat(keyfile); err != nil {
		return nil, log.Error(err)
	}
	// get key from keyfile
	key, err := readKeyfile(keyfile, passphrase)
	if err != nil {
		return nil, err
	}
	// open DB
	dbfile += fmt.Sprintf("?_pragma_key=x'%s'&_pragma_cipher_page_size=4096",
		hex.EncodeToString(key))
	// enable foreign key support
	dbfile += "&_pragma_foreign_keys=on"
	db, err := sql.Open("sqlite3", dbfile)
	if err != nil {
		return nil, log.Error(err)
	}
	// test key
	_, err = db.Exec("SELECT count(*) FROM sqlite_master;")
	if err != nil {
		return nil, log.Error(err)
	}
	return db, nil
}

// Rekey tries to rekey an encrypted database with the given newPassphrase and
// newIter many KDF iterations. The correct oldPassphrase must be supplied.
// Thereby, dbname is the prefix of the following two database files (which must
// already exist):
//
//  dbname.db
//  dbname.key
//
// Rekey replaces the dbname.key file and leaves the dbname.db file unmodified,
// allowing for very fast rekey operations. In case of error (for example, the
// database files do not exist or the oldPassphrase is wrong) an error is
// returned.
func Rekey(dbname string, oldPassphrase, newPassphrase []byte, newIter int) error {
	encdb, err := Open(dbname, oldPassphrase)
	if err != nil {
		return err
	}
	defer encdb.Close()
	keyfile := dbname + KeySuffix
	return replaceKeyfile(keyfile, oldPassphrase, newPassphrase, newIter)
}

var autoVacuumModes = []string{
	"NONE",
	"FULL",
	"INCREMENTAL",
}

// Status returns the autoVacuum and freelistCount of db.
func Status(db *sql.DB) (autoVacuum string, freelistCount int64, err error) {
	var av int64
	err = db.QueryRow("PRAGMA auto_vacuum;").Scan(&av)
	if err != nil {
		return "", 0, err
	}
	autoVacuum = autoVacuumModes[av]
	err = db.QueryRow("PRAGMA freelist_count;").Scan(&freelistCount)
	if err != nil {
		return "", 0, err
	}
	return
}

// Vacuum executes VACUUM command in db. If autoVacuumMode is not nil and
// different from the current one, the auto_vacuum mode is changed before
// VACUUM is executed.
func Vacuum(db *sql.DB, autoVacuumMode string) error {
	if autoVacuumMode != "" {
		if !util.ContainsString(autoVacuumModes, autoVacuumMode) {
			return log.Errorf("encdb: unknown auto_vacuum mode: %s", autoVacuumMode)
		}
		var av int64
		err := db.QueryRow("PRAGMA auto_vacuum;").Scan(&av)
		if err != nil {
			return err
		}
		currentMode := autoVacuumModes[av]
		if currentMode != autoVacuumMode {
			_, err = db.Exec(fmt.Sprintf("PRAGMA auto_vacuum = %s;", autoVacuumMode))
			if err != nil {
				return err
			}
		}
	}
	_, err := db.Exec("VACUUM;")
	if err != nil {
		return log.Error(err)
	}
	return nil
}

// Incremental executes incremental_vacuum to free up to pages many pages. If
// pages is 0, all pages are freed. If the current auto_vacuum mode is not
// INCREMENTAL, an error is returned.
func Incremental(db *sql.DB, pages int64) error {
	var av int64
	err := db.QueryRow("PRAGMA auto_vacuum;").Scan(&av)
	if err != nil {
		return err
	}
	if autoVacuumModes[av] != "INCREMENTAL" {
		return log.Error("encdb: current auto_vacuum mode is not INCREMENTAL")
	}
	_, err = db.Exec(fmt.Sprintf("PRAGMA incremental_vacuum(%d);", pages))
	if err != nil {
		log.Error(err)
	}
	return nil
}
<|endoftext|>


<commit_before>package via

import (
	"context"
	"github.com/ipfs/go-ipfs-api"
	"github.com/ipfs/go-ipfs/core"
	"github.com/ipfs/go-ipfs/core/coreunix"
	"os"
)

func IpfsAdd(path Path) (string, error) {
	s := shell.NewLocalShell()
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return s.Add(fd)
}

func HashOnly(path Path) (string, error) {
	node, err := core.NewNode(context.TODO(), &core.BuildCfg{NilRepo: true})
	if err != nil {
		return "", err
	}
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return coreunix.Add(node, fd)
}
<commit_msg>use go-ipfs-api for hashing<commit_after>package via

import (
	"github.com/ipfs/go-ipfs-api"
	"os"
)

func IpfsAdd(path Path) (string, error) {
	s := shell.NewLocalShell()
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return s.Add(fd)
}

func HashOnly(path Path) (string, error) {
	s := shell.NewLocalShell()
	fd, err := os.Open(path.String())
	if err != nil {
		return "", err
	}
	defer fd.Close()
	return s.Add(fd, shell.OnlyHash(true))
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package vm

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/google/mtail/metrics"
)

// Sexp is for converting program syntax trees into typed s-expression for printing
type Sexp struct {
	output string // Accumulator for the result

	emitTypes bool

	col  int // column to indent current line to
	line string
}

func (s *Sexp) indent() {
	s.col += 2
}

func (s *Sexp) outdent() {
	s.col -= 2
}

func (s *Sexp) prefix() (r string) {
	for i := 0; i < s.col; i++ {
		r += " "
	}
	return
}

func (s *Sexp) emit(str string) {
	s.line += str
}

func (s *Sexp) newline() {
	if s.line != "" {
		s.output += s.prefix() + s.line
	}
	s.output += "\n"
	s.line = ""
}

func (s *Sexp) VisitBefore(n astNode) Visitor {
	s.emit(fmt.Sprintf("( ;;%T ", n))
	if s.emitTypes {
		s.emit(fmt.Sprintf("<%s> ", n.Type()))
	}
	s.emit(fmt.Sprintf("@ %s", n.Pos()))
	s.newline()
	s.indent()
	switch v := n.(type) {

	case *patternConstNode:
		if v.name != "" {
			s.emit(fmt.Sprintf("const %q ", v.name))
		}
		s.emit(fmt.Sprintf("/%s/", v.pattern))

	case *binaryExprNode:
		switch v.op {
		case LT:
			s.emit("<")
		case GT:
			s.emit(">")
		case LE:
			s.emit("<=")
		case GE:
			s.emit(">=")
		case EQ:
			s.emit("==")
		case NE:
			s.emit("!=")
		case SHL:
			s.emit("<<")
		case SHR:
			s.emit(">>")
		case BITAND:
			s.emit("&")
		case BITOR:
			s.emit("|")
		case XOR:
			s.emit("^")
		case NOT:
			s.emit("~")
		case AND:
			s.emit("&&")
		case OR:
			s.emit("||")
		case PLUS:
			s.emit("+")
		case MINUS:
			s.emit("-")
		case MUL:
			s.emit("*")
		case DIV:
			s.emit("/")
		case POW:
			s.emit("**")
		case ASSIGN:
			s.emit("=")
		case MOD:
			s.emit("%")
		}
		s.newline()
		s.indent()

	case *idNode:
		s.emit("\"" + v.name + "\"")

	case *caprefNode:
		s.emit("\"" + v.name + "\"")

	case *builtinNode:
		s.emit("\"" + v.name + "\"")
		s.newline()

	case *declNode:
		switch v.kind {
		case metrics.Counter:
			s.emit("counter ")
		case metrics.Gauge:
			s.emit("gauge ")
		case metrics.Timer:
			s.emit("timer ")
		}
		s.emit(v.name)
		if len(v.keys) > 0 {
			s.emit(" (")
			s.emit(strings.Join(v.keys, " "))
			s.emit(")")
		}

	case *unaryExprNode:
		switch v.op {
		case INC:
			s.emit("++")
		case NOT:
			s.emit("~")
		}

	case *stringConstNode:
		s.emit("\"" + v.text + "\"")

	case *intConstNode:
		s.emit(strconv.FormatInt(v.i, 10))

	case *floatConstNode:
		s.emit(strconv.FormatFloat(v.f, 'g', -1, 64))

	case *nextNode:
		s.emit("next")
	case *otherwiseNode:
		s.emit("otherwise")
	case *delNode:
		s.emit("del")

	case *indexedExprNode, *stmtlistNode, *exprlistNode, *condNode, *defNode, *decoNode: // normal walk

	default:
		panic(fmt.Sprintf("unparser found undefined type %T", n))
	}
	return s
}

func (s *Sexp) VisitAfter(node astNode) {
	switch node.(type) {
	case *binaryExprNode:
		s.outdent()
	}
	s.outdent()
	s.emit(")")
	s.newline()
}

// Dump begins the dumping of the syntax tree, returning the s-expression as a single string
func (s *Sexp) Dump(n astNode) string {
	Walk(s, n)
	return s.output
}
<commit_msg>Print a warning if an operator is unexpected in the sexp dump.<commit_after>// Copyright 2017 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package vm

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/google/mtail/metrics"
)

// Sexp is for converting program syntax trees into typed s-expression for printing
type Sexp struct {
	output string // Accumulator for the result

	emitTypes bool

	col  int // column to indent current line to
	line string
}

func (s *Sexp) indent() {
	s.col += 2
}

func (s *Sexp) outdent() {
	s.col -= 2
}

func (s *Sexp) prefix() (r string) {
	for i := 0; i < s.col; i++ {
		r += " "
	}
	return
}

func (s *Sexp) emit(str string) {
	s.line += str
}

func (s *Sexp) newline() {
	if s.line != "" {
		s.output += s.prefix() + s.line
	}
	s.output += "\n"
	s.line = ""
}

func (s *Sexp) VisitBefore(n astNode) Visitor {
	s.emit(fmt.Sprintf("( ;;%T ", n))
	if s.emitTypes {
		s.emit(fmt.Sprintf("<%s> ", n.Type()))
	}
	s.emit(fmt.Sprintf("@ %s", n.Pos()))
	s.newline()
	s.indent()
	switch v := n.(type) {

	case *patternConstNode:
		if v.name != "" {
			s.emit(fmt.Sprintf("const %q ", v.name))
		}
		s.emit(fmt.Sprintf("/%s/", v.pattern))

	case *binaryExprNode:
		switch v.op {
		case LT:
			s.emit("<")
		case GT:
			s.emit(">")
		case LE:
			s.emit("<=")
		case GE:
			s.emit(">=")
		case EQ:
			s.emit("==")
		case NE:
			s.emit("!=")
		case SHL:
			s.emit("<<")
		case SHR:
			s.emit(">>")
		case BITAND:
			s.emit("&")
		case BITOR:
			s.emit("|")
		case XOR:
			s.emit("^")
		case NOT:
			s.emit("~")
		case AND:
			s.emit("&&")
		case OR:
			s.emit("||")
		case PLUS:
			s.emit("+")
		case MINUS:
			s.emit("-")
		case MUL:
			s.emit("*")
		case DIV:
			s.emit("/")
		case POW:
			s.emit("**")
		case ASSIGN:
			s.emit("=")
		case MOD:
			s.emit("%")
		default:
			s.emit(fmt.Sprintf("Unexpected op: %v", v.op))
		}
		s.newline()
		s.indent()

	case *idNode:
		s.emit("\"" + v.name + "\"")

	case *caprefNode:
		s.emit("\"" + v.name + "\"")

	case *builtinNode:
		s.emit("\"" + v.name + "\"")
		s.newline()

	case *declNode:
		switch v.kind {
		case metrics.Counter:
			s.emit("counter ")
		case metrics.Gauge:
			s.emit("gauge ")
		case metrics.Timer:
			s.emit("timer ")
		}
		s.emit(v.name)
		if len(v.keys) > 0 {
			s.emit(" (")
			s.emit(strings.Join(v.keys, " "))
			s.emit(")")
		}

	case *unaryExprNode:
		switch v.op {
		case INC:
			s.emit("++")
		case NOT:
			s.emit("~")
		}

	case *stringConstNode:
		s.emit("\"" + v.text + "\"")

	case *intConstNode:
		s.emit(strconv.FormatInt(v.i, 10))

	case *floatConstNode:
		s.emit(strconv.FormatFloat(v.f, 'g', -1, 64))

	case *nextNode:
		s.emit("next")
	case *otherwiseNode:
		s.emit("otherwise")
	case *delNode:
		s.emit("del")

	case *indexedExprNode, *stmtlistNode, *exprlistNode, *condNode, *defNode, *decoNode: // normal walk

	default:
		panic(fmt.Sprintf("unparser found undefined type %T", n))
	}
	return s
}

func (s *Sexp) VisitAfter(node astNode) {
	switch node.(type) {
	case *binaryExprNode:
		s.outdent()
	}
	s.outdent()
	s.emit(")")
	s.newline()
}

// Dump begins the dumping of the syntax tree, returning the s-expression as a single string
func (s *Sexp) Dump(n astNode) string {
	Walk(s, n)
	return s.output
}
<|endoftext|>


<commit_before>package eqemuconfig

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

type Config struct {
	Shortname string   `xml:"world>shortname"`
	Longame   string   `xml:"world>longname"`
	Database  Database `xml:"database,omitempty"`
	QuestsDir string   `xml:"directories>quests,omitempty"`
	Discord   Discord  `xml:"discord,omitempty"`
}

type Database struct {
	Host     string `xml:"host"`
	Port     string `xml:"port"`
	Username string `xml:"username"`
	Password string `xml:"password"`
	Db       string `xml:"db"`
}

type Discord struct {
	Username    string    `xml:"username,omitempty"`
	Password    string    `xml:"password,omitempty"`
	ServerID    string    `xml:"serverid,omitempty"`
	ChannelID   string    `xml:"channelid,omitempty"`
	RefreshRate int64     `xml:"refreshrate,omitempty"`
	Channels    []Channel `xml:"channel"`
}

type Channel struct {
	ChannelID   string `xml:"channelid,attr"`
	ChannelName string `xml:"channelname,attr"`
}

var config *Config

func GetConfig() (respConfig *Config, err error) {
	if config != nil {
		respConfig = config
		return
	}

	f, err := os.Open("eqemu_config.xml")
	if err != nil {
		err = fmt.Errorf("Error opening config: %s", err.Error())
		return
	}
	config = &Config{}
	dec := xml.NewDecoder(f)
	err = dec.Decode(config)
	if err != nil {
		if !strings.Contains(err.Error(), "EOF") {
			err = fmt.Errorf("Error decoding config: %s", err.Error())
			return
		}

		//This may be a ?> issue, let's fix it.
		bConfig, rErr := ioutil.ReadFile("eqemu_config.xml")
		if rErr != nil {
			err = fmt.Errorf("Error reading config: %s", rErr.Error())
			return
		}
		strConfig := strings.Replace(string(bConfig), "<?xml version=\"1.0\">", "<?xml version=\"1.0\"?>", 1)
		err = xml.Unmarshal([]byte(strConfig), config)
		if err != nil {
			err = fmt.Errorf("Failed to unmarshal config: %s", err.Error())
			return
		}
	}
	err = f.Close()
	if err != nil {
		err = fmt.Errorf("Failed to close config: %s", err.Error())
		return
	}
	if config.QuestsDir == "" {
		config.QuestsDir = "quests"
	}
	respConfig = config
	return
}
<commit_msg>Added Twitter Oauth struct<commit_after>package eqemuconfig

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

type Config struct {
	Shortname string    `xml:"world>shortname"`
	Longame   string    `xml:"world>longname"`
	Database  Database  `xml:"database,omitempty"`
	QuestsDir string    `xml:"directories>quests,omitempty"`
	Discord   Discord   `xml:"discord,omitempty"`
	Twitter   []Twitter `xml:"twitter,omitempty"`
}

type Database struct {
	Host     string `xml:"host"`
	Port     string `xml:"port"`
	Username string `xml:"username"`
	Password string `xml:"password"`
	Db       string `xml:"db"`
}

type Discord struct {
	Username    string    `xml:"username,omitempty"`
	Password    string    `xml:"password,omitempty"`
	ServerID    string    `xml:"serverid,omitempty"`
	ChannelID   string    `xml:"channelid,omitempty"`
	RefreshRate int64     `xml:"refreshrate,omitempty"`
	Channels    []Channel `xml:"channel"`
}

type Channel struct {
	ChannelID   string `xml:"channelid,attr"`
	ChannelName string `xml:"channelname,attr"`
}

type Twitter struct {
	Owner             string `xml:"owner,attr,omitempty"`
	ConsumerKey       string `xml:"consumerkey,attr,omitempty"`
	ConsumerSecret    string `xml:"consumersecret,attr,omitempty"`
	AccessToken       string `xml:"accesstoken,attr,omitempty"`
	AccessTokenSecret string `xml:"accesstokensecret,attr,omitempty"`
}

type Graph struct {
	TablePrefix string `xml:"tableprefix,attr,omitempty"`
}

var config *Config

func GetConfig() (respConfig *Config, err error) {
	if config != nil {
		respConfig = config
		return
	}

	f, err := os.Open("eqemu_config.xml")
	if err != nil {
		err = fmt.Errorf("Error opening config: %s", err.Error())
		return
	}
	config = &Config{}
	dec := xml.NewDecoder(f)
	err = dec.Decode(config)
	if err != nil {
		if !strings.Contains(err.Error(), "EOF") {
			err = fmt.Errorf("Error decoding config: %s", err.Error())
			return
		}

		//This may be a ?> issue, let's fix it.
		bConfig, rErr := ioutil.ReadFile("eqemu_config.xml")
		if rErr != nil {
			err = fmt.Errorf("Error reading config: %s", rErr.Error())
			return
		}
		strConfig := strings.Replace(string(bConfig), "<?xml version=\"1.0\">", "<?xml version=\"1.0\"?>", 1)
		err = xml.Unmarshal([]byte(strConfig), config)
		if err != nil {
			err = fmt.Errorf("Failed to unmarshal config: %s", err.Error())
			return
		}
	}
	err = f.Close()
	if err != nil {
		err = fmt.Errorf("Failed to close config: %s", err.Error())
		return
	}
	if config.QuestsDir == "" {
		config.QuestsDir = "quests"
	}
	respConfig = config
	return
}
<|endoftext|>


<commit_before>package bundler

// This test file contains tests on checking the correctness of BundleFromRemote
import (
	"flag"
	"testing"

	"github.com/cloudflare/cfssl/ubiquity"
)

var shouldTestSNI bool

func init() {
	flag.BoolVar(&shouldTestSNI, "test-sni", false, "run the SNI tests")
	flag.Parse()
}

// remoteTest defines a test case for BundleFromRemote. Hostname and ip are the test inputs.
// bundlerConstructor points the bundler ctor and errorCallback handles the error checking.
type remoteTest struct {
	hostname           string
	ip                 string
	bundlerConstructor func(*testing.T) (b *Bundler)
	errorCallback      func(*testing.T, error)
	bundleCallback     func(*testing.T, *Bundle)
}

const (
	ValidSSLSite           = "google.com"
	SelfSignedSSLSite      = "cacert.org"
	MismatchedHostnameSite = "www.capitol.state.tx.us"
	ExpiredCertSite        = "testssl-expire.disig.sk"
	ECCCertSite            = "benflare.us"
	InvalidSite            = "cloudflare1337.com"
	ValidSNI               = "alice.sni.velox.ch"
	ValidSNIWildcard       = "cloudflare.sni.velox.ch"
	SNISANWildcard         = "*.sni.velox.ch"
	ValidSNIIP             = "85.25.46.13"
	InvalidIP              = "300.300.300.300"
)

func getBundleHostnameChecker(hostname string) func(*testing.T, *Bundle) {
	return func(t *testing.T, bundle *Bundle) {
		if bundle == nil {
			t.Fatalf("Nil bundle returned")
		}
		var found = false
		for _, h := range bundle.Hostnames {
			if h == hostname {
				found = true
			}
		}
		if !found {
			t.Errorf("hostname expected but not found: %s", hostname)
		}
	}
}

// test cases of BundleFromRemote
var remoteTests = []remoteTest{
	{
		hostname:           ValidSSLSite,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
	},
	{
		hostname:           SelfSignedSSLSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":12`}), // only check it is a 12xx error
	},
	{
		hostname:           MismatchedHostnameSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":12`}), // only check it is a 12xx error
	},
	{
		hostname:           ExpiredCertSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":12`}), // only check it is a 12xx error
	},
	{
		hostname:           InvalidSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":6000`, "dial tcp: lookup cloudflare1337.com"}),
	},
	{
		hostname:           InvalidIP,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":6000`, "dial tcp: lookup 300.300.300.300"}),
	},
	{
		ip:                 InvalidIP,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":6000`, "dial tcp: lookup 300.300.300.300"}),
	},
}

// TestBundleFromRemote goes through the test cases defined in remoteTests and run them through. See above for test case definitions.
func TestBundleFromRemote(t *testing.T) {
	for _, bf := range []BundleFlavor{Ubiquitous, Optimal} {
		for _, test := range remoteTests {
			b := test.bundlerConstructor(t)
			bundle, err := b.BundleFromRemote(test.hostname, test.ip, bf)
			if test.errorCallback != nil {
				test.errorCallback(t, err)
			} else {
				if err != nil {
					t.Fatal("expected no error. but an error occurred", err.Error())
				}
				if test.bundleCallback != nil {
					test.bundleCallback(t, bundle)
				}
			}
		}
	}
}

var remoteSNITests = []remoteTest{
	{
		hostname:           ValidSNI,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(ValidSNI),
	},
	{
		hostname:           ValidSNIWildcard,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(SNISANWildcard),
	},
	{
		hostname:           ValidSNI,
		ip:                 ValidSNIIP,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(ValidSNI),
	},
	{
		hostname:           ValidSNIWildcard,
		ip:                 ValidSNIIP,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(SNISANWildcard),
	},
}

// TestBundleFromRemoteSNI goes through the test cases defined in remoteSNITests and run them through. See above for test case definitions.
func TestBundleFromRemoteSNI(t *testing.T) {
	if !shouldTestSNI {
		t.Skip()
	}
	for _, bf := range []BundleFlavor{Ubiquitous, Optimal} {
		for _, test := range remoteSNITests {
			b := test.bundlerConstructor(t)
			bundle, err := b.BundleFromRemote(test.hostname, test.ip, bf)
			if test.errorCallback != nil {
				test.errorCallback(t, err)
			} else {
				if err != nil {
					t.Errorf("expected no error. but an error occurred: %s", err.Error())
				}
				if test.bundleCallback != nil {
					test.bundleCallback(t, bundle)
				}
			}
		}
	}
}

func TestBundleFromRemoteFlavor(t *testing.T) {
	b := newBundler(t)
	ubiquity.Platforms = nil
	ubiquity.LoadPlatforms(testMetadata)

	bundle, err := b.BundleFromRemote(ECCCertSite, "", Ubiquitous)
	if err != nil {
		t.Fatalf("expected no error. but an error occurred: %s", err.Error())
	}
	if len(bundle.Chain) != 3 {
		t.Error("expected 3-cert bundle. Got ", len(bundle.Chain))
	}
	if len(bundle.Status.Untrusted) != 0 {
		t.Error("expected no untrusted platforms. Got ", bundle.Status.Untrusted)
	}

	bundle, err = b.BundleFromRemote(ECCCertSite, "", Optimal)
	if err != nil {
		t.Errorf("expected no error. but an error occurred: %s", err.Error())
	}
	if len(bundle.Chain) != 2 {
		t.Error("expected 2-cert bundle. Got ", len(bundle.Chain))
	}

}
<commit_msg>remove a invalid remote bundle test<commit_after>package bundler

// This test file contains tests on checking the correctness of BundleFromRemote
import (
	"flag"
	"testing"

	"github.com/cloudflare/cfssl/ubiquity"
)

var shouldTestSNI bool

func init() {
	flag.BoolVar(&shouldTestSNI, "test-sni", false, "run the SNI tests")
	flag.Parse()
}

// remoteTest defines a test case for BundleFromRemote. Hostname and ip are the test inputs.
// bundlerConstructor points the bundler ctor and errorCallback handles the error checking.
type remoteTest struct {
	hostname           string
	ip                 string
	bundlerConstructor func(*testing.T) (b *Bundler)
	errorCallback      func(*testing.T, error)
	bundleCallback     func(*testing.T, *Bundle)
}

const (
	ValidSSLSite           = "google.com"
	SelfSignedSSLSite      = "cacert.org"
	MismatchedHostnameSite = "www.capitol.state.tx.us"
	ECCCertSite            = "benflare.us"
	InvalidSite            = "cloudflare1337.com"
	ValidSNI               = "alice.sni.velox.ch"
	ValidSNIWildcard       = "cloudflare.sni.velox.ch"
	SNISANWildcard         = "*.sni.velox.ch"
	ValidSNIIP             = "85.25.46.13"
	InvalidIP              = "300.300.300.300"
)

func getBundleHostnameChecker(hostname string) func(*testing.T, *Bundle) {
	return func(t *testing.T, bundle *Bundle) {
		if bundle == nil {
			t.Fatalf("Nil bundle returned")
		}
		var found = false
		for _, h := range bundle.Hostnames {
			if h == hostname {
				found = true
			}
		}
		if !found {
			t.Errorf("hostname expected but not found: %s", hostname)
		}
	}
}

// test cases of BundleFromRemote
var remoteTests = []remoteTest{
	{
		hostname:           ValidSSLSite,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
	},
	{
		hostname:           SelfSignedSSLSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":12`}), // only check it is a 12xx error
	},
	{
		hostname:           MismatchedHostnameSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":12`}), // only check it is a 12xx error
	},
	{
		hostname:           InvalidSite,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":6000`, "dial tcp: lookup cloudflare1337.com"}),
	},
	{
		hostname:           InvalidIP,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":6000`, "dial tcp: lookup 300.300.300.300"}),
	},
	{
		ip:                 InvalidIP,
		bundlerConstructor: newBundler,
		errorCallback:      ExpectErrorMessages([]string{`"code":6000`, "dial tcp: lookup 300.300.300.300"}),
	},
}

// TestBundleFromRemote goes through the test cases defined in remoteTests and run them through. See above for test case definitions.
func TestBundleFromRemote(t *testing.T) {
	for _, bf := range []BundleFlavor{Ubiquitous, Optimal} {
		for _, test := range remoteTests {
			b := test.bundlerConstructor(t)
			bundle, err := b.BundleFromRemote(test.hostname, test.ip, bf)
			if test.errorCallback != nil {
				test.errorCallback(t, err)
			} else {
				if err != nil {
					t.Fatal("expected no error. but an error occurred", err.Error())
				}
				if test.bundleCallback != nil {
					test.bundleCallback(t, bundle)
				}
			}
		}
	}
}

var remoteSNITests = []remoteTest{
	{
		hostname:           ValidSNI,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(ValidSNI),
	},
	{
		hostname:           ValidSNIWildcard,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(SNISANWildcard),
	},
	{
		hostname:           ValidSNI,
		ip:                 ValidSNIIP,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(ValidSNI),
	},
	{
		hostname:           ValidSNIWildcard,
		ip:                 ValidSNIIP,
		bundlerConstructor: newBundler,
		errorCallback:      nil,
		bundleCallback:     getBundleHostnameChecker(SNISANWildcard),
	},
}

// TestBundleFromRemoteSNI goes through the test cases defined in remoteSNITests and run them through. See above for test case definitions.
func TestBundleFromRemoteSNI(t *testing.T) {
	if !shouldTestSNI {
		t.Skip()
	}
	for _, bf := range []BundleFlavor{Ubiquitous, Optimal} {
		for _, test := range remoteSNITests {
			b := test.bundlerConstructor(t)
			bundle, err := b.BundleFromRemote(test.hostname, test.ip, bf)
			if test.errorCallback != nil {
				test.errorCallback(t, err)
			} else {
				if err != nil {
					t.Errorf("expected no error. but an error occurred: %s", err.Error())
				}
				if test.bundleCallback != nil {
					test.bundleCallback(t, bundle)
				}
			}
		}
	}
}

func TestBundleFromRemoteFlavor(t *testing.T) {
	b := newBundler(t)
	ubiquity.Platforms = nil
	ubiquity.LoadPlatforms(testMetadata)

	bundle, err := b.BundleFromRemote(ECCCertSite, "", Ubiquitous)
	if err != nil {
		t.Fatalf("expected no error. but an error occurred: %s", err.Error())
	}
	if len(bundle.Chain) != 3 {
		t.Error("expected 3-cert bundle. Got ", len(bundle.Chain))
	}
	if len(bundle.Status.Untrusted) != 0 {
		t.Error("expected no untrusted platforms. Got ", bundle.Status.Untrusted)
	}

	bundle, err = b.BundleFromRemote(ECCCertSite, "", Optimal)
	if err != nil {
		t.Errorf("expected no error. but an error occurred: %s", err.Error())
	}
	if len(bundle.Chain) != 2 {
		t.Error("expected 2-cert bundle. Got ", len(bundle.Chain))
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"

	"github.com/streadway/amqp"
)

func Receive() {
	conn, err := amqp.Dial("amqp://guest:guest@cerbercam.cloudapp.net:5672/")
	failOnError(err, "Failed to connect to RabbitMQ")

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")

	q, err := ch.QueueDeclare(
		"picturesQueue", // name
		false,           // durable
		false,           // delete when unused
		false,           // exclusive
		false,           // no-wait
		nil,             // arguments
	)
	failOnError(err, "Failed to declare a queue")

	msgs, err := ch.Consume(
		q.Name, // queue
		"",     // consumer
		true,   // auto-ack
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)
	failOnError(err, "Failed to register a consumer")

	go func() {
		for d := range msgs {
			fmt.Print("Received a message: %s", d.Body)
		}
	}()

	defer ch.Close()
	defer conn.Close()
}

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}
<commit_msg>Replaced log with go-logging<commit_after>package main

import (
	"fmt"

	"github.com/op/go-logging"
	"github.com/streadway/amqp"
)

var log = logging.MustGetLogger("logger")

func Receive() {
	conn, err := amqp.Dial("amqp://guest:guest@cerbercam.cloudapp.net:5672/")
	failOnError(err, "Failed to connect to RabbitMQ")

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")

	q, err := ch.QueueDeclare(
		"picturesQueue", // name
		false,           // durable
		false,           // delete when unused
		false,           // exclusive
		false,           // no-wait
		nil,             // arguments
	)
	failOnError(err, "Failed to declare a queue")

	msgs, err := ch.Consume(
		q.Name, // queue
		"",     // consumer
		true,   // auto-ack
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)
	failOnError(err, "Failed to register a consumer")

	go func() {
		for d := range msgs {
			fmt.Print("Received a message: %s", d.Body)
		}
	}()

	defer ch.Close()
	defer conn.Close()
}

func failOnError(err error, msg string) {
	if err != nil {
		log.Criticalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}
<|endoftext|>


<commit_before>package registry

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"net/http"
	"runtime"
	"time"

	consul "github.com/hashicorp/consul/api"
)

type consulRegistry struct {
	Address string
	Client  *consul.Client
	Options Options
}

func newTransport(config *tls.Config) *http.Transport {
	if config == nil {
		config = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	t := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig:     config,
	}
	runtime.SetFinalizer(&t, func(tr **http.Transport) {
		(*tr).CloseIdleConnections()
	})
	return t
}

func encodeEndpoints(en []*Endpoint) []string {
	var tags []string
	for _, e := range en {
		if b, err := json.Marshal(e); err == nil {
			tags = append(tags, "e="+string(b))
		}
	}
	return tags
}

func decodeEndpoints(tags []string) []*Endpoint {
	var en []*Endpoint
	for _, tag := range tags {
		if len(tag) == 0 || tag[0] != 'e' {
			continue
		}

		var e *Endpoint
		if err := json.Unmarshal([]byte(tag[2:]), &e); err == nil {
			en = append(en, e)
		}
	}
	return en
}

func encodeMetadata(md map[string]string) []string {
	var tags []string
	for k, v := range md {
		if b, err := json.Marshal(map[string]string{
			k: v,
		}); err == nil {
			tags = append(tags, "t="+string(b))
		}
	}
	return tags
}

func decodeMetadata(tags []string) map[string]string {
	md := make(map[string]string)
	for _, tag := range tags {
		if len(tag) == 0 || tag[0] != 't' {
			continue
		}

		var kv map[string]string
		if err := json.Unmarshal([]byte(tag[2:]), &kv); err == nil {
			for k, v := range kv {
				md[k] = v
			}
		}
	}
	return md
}

func newConsulRegistry(addrs []string, opts ...Option) Registry {
	var opt Options
	for _, o := range opts {
		o(&opt)
	}

	// use default config
	config := consul.DefaultConfig()

	// set timeout
	if opt.Timeout > 0 {
		config.HttpClient.Timeout = opt.Timeout
	}

	// check if there are any addrs
	if len(addrs) > 0 {
		addr, port, err := net.SplitHostPort(addrs[0])
		if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
			port = "8500"
			config.Address = fmt.Sprintf("%s:%s", addr, port)
		} else if err == nil {
			config.Address = fmt.Sprintf("%s:%s", addr, port)
		}
	}

	// requires secure connection?
	if opt.Secure || opt.TLSConfig != nil {
		config.Scheme = "https"
		// We're going to support InsecureSkipVerify
		config.HttpClient.Transport = newTransport(opt.TLSConfig)
	}

	// create the client
	client, _ := consul.NewClient(config)

	cr := &consulRegistry{
		Address: config.Address,
		Client:  client,
		Options: opt,
	}

	return cr
}

func (c *consulRegistry) Deregister(s *Service) error {
	if len(s.Nodes) == 0 {
		return errors.New("Require at least one node")
	}

	node := s.Nodes[0]

	_, err := c.Client.Catalog().Deregister(&consul.CatalogDeregistration{
		Node:    node.Id,
		Address: node.Address,
	}, nil)

	return err
}

func (c *consulRegistry) Register(s *Service) error {
	if len(s.Nodes) == 0 {
		return errors.New("Require at least one node")
	}

	node := s.Nodes[0]

	tags := encodeMetadata(node.Metadata)
	tags = append(tags, encodeEndpoints(s.Endpoints)...)

	_, err := c.Client.Catalog().Register(&consul.CatalogRegistration{
		Node:    node.Id,
		Address: node.Address,
		Service: &consul.AgentService{
			ID:      s.Version,
			Service: s.Name,
			Port:    node.Port,
			Tags:    tags,
		},
	}, nil)

	return err
}

func (c *consulRegistry) GetService(name string) ([]*Service, error) {
	rsp, _, err := c.Client.Catalog().Service(name, "", nil)
	if err != nil {
		return nil, err
	}

	serviceMap := map[string]*Service{}

	for _, s := range rsp {
		if s.ServiceName != name {
			continue
		}

		id := s.Node
		key := s.ServiceID
		version := s.ServiceID

		// We're adding service version but
		// don't want to break backwards compatibility
		if id == version {
			key = "default"
			version = ""
		}

		svc, ok := serviceMap[key]
		if !ok {
			svc = &Service{
				Endpoints: decodeEndpoints(s.ServiceTags),
				Name:      s.ServiceName,
				Version:   version,
			}
			serviceMap[key] = svc
		}

		svc.Nodes = append(svc.Nodes, &Node{
			Id:       id,
			Address:  s.Address,
			Port:     s.ServicePort,
			Metadata: decodeMetadata(s.ServiceTags),
		})
	}

	var services []*Service
	for _, service := range serviceMap {
		services = append(services, service)
	}
	return services, nil
}

func (c *consulRegistry) ListServices() ([]*Service, error) {
	rsp, _, err := c.Client.Catalog().Services(nil)
	if err != nil {
		return nil, err
	}

	var services []*Service

	for service, _ := range rsp {
		services = append(services, &Service{Name: service})
	}

	return services, nil
}

func (c *consulRegistry) Watch() (Watcher, error) {
	return newConsulWatcher(c)
}

func (c *consulRegistry) String() string {
	return "consul"
}
<commit_msg>Use ServiceID as node.ID rather than Node.... in time remove Node/Address completely<commit_after>package registry

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"net/http"
	"os"
	"runtime"
	"time"

	consul "github.com/hashicorp/consul/api"
)

type consulRegistry struct {
	Address string
	Client  *consul.Client
	Options Options
}

func newTransport(config *tls.Config) *http.Transport {
	if config == nil {
		config = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	t := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig:     config,
	}
	runtime.SetFinalizer(&t, func(tr **http.Transport) {
		(*tr).CloseIdleConnections()
	})
	return t
}

func encodeEndpoints(en []*Endpoint) []string {
	var tags []string
	for _, e := range en {
		if b, err := json.Marshal(e); err == nil {
			tags = append(tags, "e="+string(b))
		}
	}
	return tags
}

func decodeEndpoints(tags []string) []*Endpoint {
	var en []*Endpoint
	for _, tag := range tags {
		if len(tag) == 0 || tag[0] != 'e' {
			continue
		}

		var e *Endpoint
		if err := json.Unmarshal([]byte(tag[2:]), &e); err == nil {
			en = append(en, e)
		}
	}
	return en
}

func encodeMetadata(md map[string]string) []string {
	var tags []string
	for k, v := range md {
		if b, err := json.Marshal(map[string]string{
			k: v,
		}); err == nil {
			tags = append(tags, "t="+string(b))
		}
	}
	return tags
}

func decodeMetadata(tags []string) map[string]string {
	md := make(map[string]string)
	for _, tag := range tags {
		if len(tag) == 0 || tag[0] != 't' {
			continue
		}

		var kv map[string]string
		if err := json.Unmarshal([]byte(tag[2:]), &kv); err == nil {
			for k, v := range kv {
				md[k] = v
			}
		}
	}
	return md
}

func encodeVersion(v string) string {
	return "v=" + v
}

func decodeVersion(tags []string) (string, bool) {
	for _, tag := range tags {
		if len(tag) == 0 || tag[0] != 'v' {
			continue
		}
		return tag[2:], true
	}
	return "", false
}

func newConsulRegistry(addrs []string, opts ...Option) Registry {
	var opt Options
	for _, o := range opts {
		o(&opt)
	}

	// use default config
	config := consul.DefaultConfig()

	// set timeout
	if opt.Timeout > 0 {
		config.HttpClient.Timeout = opt.Timeout
	}

	// check if there are any addrs
	if len(addrs) > 0 {
		addr, port, err := net.SplitHostPort(addrs[0])
		if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
			port = "8500"
			addr = addrs[0]
			config.Address = fmt.Sprintf("%s:%s", addr, port)
		} else if err == nil {
			config.Address = fmt.Sprintf("%s:%s", addr, port)
		}
	}

	// requires secure connection?
	if opt.Secure || opt.TLSConfig != nil {
		config.Scheme = "https"
		// We're going to support InsecureSkipVerify
		config.HttpClient.Transport = newTransport(opt.TLSConfig)
	}

	// create the client
	client, _ := consul.NewClient(config)

	cr := &consulRegistry{
		Address: config.Address,
		Client:  client,
		Options: opt,
	}

	return cr
}

func (c *consulRegistry) Deregister(s *Service) error {
	if len(s.Nodes) == 0 {
		return errors.New("Require at least one node")
	}
	return c.Client.Agent().ServiceDeregister(s.Nodes[0].Id)
}

func (c *consulRegistry) Register(s *Service) error {
	if len(s.Nodes) == 0 {
		return errors.New("Require at least one node")
	}

	node := s.Nodes[0]

	tags := encodeMetadata(node.Metadata)
	tags = append(tags, encodeEndpoints(s.Endpoints)...)
	tags = append(tags, encodeVersion(s.Version))

	if _, err := c.Client.Catalog().Register(&consul.CatalogRegistration{
		// TODO: remove setting node and address
		Node:    node.Id,
		Address: node.Address,
		Service: &consul.AgentService{
			ID:      node.Id,
			Service: s.Name,
			Port:    node.Port,
			Tags:    tags,
			Address: node.Address,
		},
	}, nil); err != nil {
		return err
	}

	return nil
}

func (c *consulRegistry) GetService(name string) ([]*Service, error) {
	rsp, _, err := c.Client.Catalog().Service(name, "", nil)
	if err != nil {
		return nil, err
	}

	serviceMap := map[string]*Service{}

	for _, s := range rsp {
		if s.ServiceName != name {
			continue
		}

		// version is now a tag
		version, found := decodeVersion(s.ServiceTags)
		// service ID is now the node id
		id := s.ServiceID
		// key is always the version
		key := version
		// address is service address
		address := s.ServiceAddress

		// if we can't get the new type of version
		// use old the old ways
		if !found {
			// id was set as node
			id = s.Node
			// key was service id
			key = s.ServiceID
			// version was service id
			version = s.ServiceID
			// address was address
			address = s.Address
		}

		svc, ok := serviceMap[key]
		if !ok {
			svc = &Service{
				Endpoints: decodeEndpoints(s.ServiceTags),
				Name:      s.ServiceName,
				Version:   version,
			}
			serviceMap[key] = svc
		}

		svc.Nodes = append(svc.Nodes, &Node{
			Id:       id,
			Address:  address,
			Port:     s.ServicePort,
			Metadata: decodeMetadata(s.ServiceTags),
		})
	}

	var services []*Service
	for _, service := range serviceMap {
		services = append(services, service)
	}
	return services, nil
}

func (c *consulRegistry) ListServices() ([]*Service, error) {
	rsp, _, err := c.Client.Catalog().Services(nil)
	if err != nil {
		return nil, err
	}

	var services []*Service

	for service, _ := range rsp {
		services = append(services, &Service{Name: service})
	}

	return services, nil
}

func (c *consulRegistry) Watch() (Watcher, error) {
	return newConsulWatcher(c)
}

func (c *consulRegistry) String() string {
	return "consul"
}
<|endoftext|>


<commit_before>package handler

import (
	"context"

	"github.com/micro/go-micro/errors"
	"github.com/micro/go-micro/registry"
	pb "github.com/micro/go-micro/registry/proto"
	"github.com/micro/go-micro/registry/service"
)

type Registry struct {
	// internal registry
	Registry registry.Registry
}

func (r *Registry) GetService(ctx context.Context, req pb.GetRequest, rsp pb.GetResponse) error {
	services, err := r.Registry.GetService(req.Service)
	for _, srv := range services {
		rsp.Services = append(rsp.Services, service.ToProto(srv))
	}
	return nil
}

func (r *Registry) Register(ctx context.Context, req pb.Service, rsp pb.EmptyResponse) error {
	err := r.Registry.Register(service.ToService(req.Service))
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}
	return nil
}

func (r *Registry) Deregister(ctx context.Context, req pb.Service, rsp pb.EmptyResponse) error {
	err := r.Registry.Deregister(service.ToService(req.Service))
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}
	return nil
}

func (r *Registry) ListServices(ctx context.Context, req pb.ListRequest, rsp pb.ListResponse) error {
	services, err := r.Registry.ListServices()
	for _, srv := range services {
		rsp.Services = append(rsp.Services, service.ToProto(srv))
	}
	return nil
}

func (r *Registry) Watch(ctx context.Context, req pb.WatchRequest, rsp pb.Registry_WatchStream) error {
	watcher, err := r.Registry.Watcher(registry.WatchOption(req.Service))
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}

	for {
		next, err := watcher.Next()
		if err != nil {
			return errors.InternalServerError("go.micro.registry", err.Error())
		}
		err = rsp.Send(&pb.Result{
			Action:  next.Action,
			Service: service.ToProto(next.Service),
		})
		if err != nil {
			return errors.InternalServerError("go.micro.registry", err.Error())
		}
	}

	return nil
}
<commit_msg>Fix build breaks<commit_after>package handler

import (
	"context"

	"github.com/micro/go-micro/errors"
	"github.com/micro/go-micro/registry"
	pb "github.com/micro/go-micro/registry/proto"
	"github.com/micro/go-micro/registry/service"
)

type Registry struct {
	// internal registry
	Registry registry.Registry
}

func (r *Registry) GetService(ctx context.Context, req *pb.GetRequest, rsp *pb.GetResponse) error {
	services, err := r.Registry.GetService(req.Service)
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}
	for _, srv := range services {
		rsp.Services = append(rsp.Services, service.ToProto(srv))
	}
	return nil
}

func (r *Registry) Register(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error {
	err := r.Registry.Register(service.ToService(req))
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}
	return nil
}

func (r *Registry) Deregister(ctx context.Context, req *pb.Service, rsp *pb.EmptyResponse) error {
	err := r.Registry.Deregister(service.ToService(req))
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}
	return nil
}

func (r *Registry) ListServices(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error {
	services, err := r.Registry.ListServices()
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}
	for _, srv := range services {
		rsp.Services = append(rsp.Services, service.ToProto(srv))
	}
	return nil
}

func (r *Registry) Watch(ctx context.Context, req *pb.WatchRequest, rsp pb.Registry_WatchStream) error {
	watcher, err := r.Registry.Watch(registry.WatchService(req.Service))
	if err != nil {
		return errors.InternalServerError("go.micro.registry", err.Error())
	}

	for {
		next, err := watcher.Next()
		if err != nil {
			return errors.InternalServerError("go.micro.registry", err.Error())
		}
		err = rsp.Send(&pb.Result{
			Action:  next.Action,
			Service: service.ToProto(next.Service),
		})
		if err != nil {
			return errors.InternalServerError("go.micro.registry", err.Error())
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package watcher

import (
	"errors"
	"os"
	"path/filepath"
	"time"
)

var (
	// ErrNothingAdded is an error that occurs when a Watcher's Start() method is
	// called and no files or folders have been added to the Watcher's watchlist.
	ErrNothingAdded = errors.New("error: no files added to the watchlist")

	// ErrWatchedFileDeleted is an error that occurs when a file or folder that was
	// being watched has been deleted.
	ErrWatchedFileDeleted = errors.New("error: watched file or folder deleted")
)

// An EventType is a type that is used to describe what type
// of event has occured during the watching process.
type EventType int

const (
	EventFileAdded EventType = 1 << iota
	EventFileDeleted
	EventFileModified
)

// String returns a small string depending on what
// type of event it is.
func (e EventType) String() string {
	switch e {
	case EventFileAdded:
		return "FILE/FOLDER ADDED"
	case EventFileDeleted:
		return "FILE/FOLDER DELETED"
	case EventFileModified:
		return "FILE/FOLDER MODIFIED"
	default:
		return "UNRECOGNIZED EVENT"
	}
}

type Event struct {
	EventType
	File
}

// A Watcher describes a file watcher.
type Watcher struct {
	Names []string
	Files []File
	Event chan Event
	Error chan error
}

// A Watcher describes a file/folder being watched.
type File struct {
	Dir string
	os.FileInfo
}

// New returns a new initialized *Watcher.
func New() *Watcher {
	return &Watcher{
		Names: []string{},
		Files: []File{},
		Event: make(chan Event),
		Error: make(chan error),
	}
}

// fileInfo is an implementation of os.FileInfo that can be used
// as a mocked os.FileInfo when triggering an event when the specified
// File is nil.
type fileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	sys     interface{}
}

func (fs *fileInfo) IsDir() bool {
	return false
}
func (fs *fileInfo) ModTime() time.Time {
	return fs.modTime
}
func (fs *fileInfo) Mode() os.FileMode {
	return fs.mode
}
func (fs *fileInfo) Name() string {
	return fs.name
}
func (fs *fileInfo) Size() int64 {
	return fs.size
}
func (fs *fileInfo) Sys() interface{} {
	return fs.sys
}

// Trigger is a method that can be used to trigger an event, separate to
// the file watching process.
func (w *Watcher) Trigger(event EventType, file os.FileInfo) {
	if file == nil {
		file = &fileInfo{name: "triggered event", modTime: time.Now()}
	}
	w.Event <- Event{event, File{FileInfo: file}}
}

// Add adds either a single file or recursed directory to
// the Watcher's file list.
func (w *Watcher) Add(name string) error {
	// Add the name from w's Names list.
	w.Names = append(w.Names, name)

	// Make sure name exists.
	fInfo, err := os.Stat(name)
	if err != nil {
		return err
	}

	// If watching a single file, add it and return.
	if !fInfo.IsDir() {
		w.Files = append(w.Files, File{Dir: filepath.Dir(fInfo.Name()), FileInfo: fInfo})
		return nil
	}

	// Add all of the os.FileInfo's to w from dir recursively.
	fInfoList, err := ListFiles(name)
	if err != nil {
		return err
	}
	w.Files = append(w.Files, fInfoList...)
	return nil
}

// Remove removes either a single file or recursed directory from
// the Watcher's file list.
func (w *Watcher) Remove(name string) error {
	// Remove the name from w's Names list.
	for i := range w.Names {
		if w.Names[i] == name {
			w.Names = append(w.Names[:i], w.Names[i+1:]...)
		}
	}

	// Make sure name exists.
	fInfo, err := os.Stat(name)
	if err != nil {
		return err
	}

	// If name is a single file, remove it and return.
	if !fInfo.IsDir() {
		for i := range w.Files {
			if w.Files[i].FileInfo == fInfo &&
				w.Files[i].Dir == filepath.Dir(fInfo.Name()) {
				w.Files = append(w.Files[:i], w.Files[i+1:]...)
			}
		}
		return nil
	}

	// Retrieve a list of all of the os.FileInfo's to delete from w.Files.
	fileList, err := ListFiles(name)
	if err != nil {
		return err
	}

	// Remove the appropriate os.FileInfo's from w's os.FileInfo list.
	for _, file := range fileList {
		for i, wFile := range w.Files {
			if wFile.Dir == file.Dir &&
				wFile.Name() == file.Name() {
				w.Files = append(w.Files[:i], w.Files[i+1:]...)
			}
		}
	}
	return nil
}

// Start starts the watching process and checks for changes every `pollInterval`
// amount of milliseconds. If pollInterval is 0, the default is 100ms.
func (w *Watcher) Start(pollInterval int) error {
	if pollInterval == 0 {
		pollInterval = 100
	}

	if len(w.Names) < 1 {
		return ErrNothingAdded
	}

	for {
		var fileList []File
		for _, name := range w.Names {
			// Retrieve the list of os.FileInfo's from w.Name.
			list, err := ListFiles(name)
			if err != nil {
				if os.IsNotExist(err) {
					w.Error <- ErrWatchedFileDeleted
				} else {
					w.Error <- err
				}
			}
			fileList = append(fileList, list...)
		}

		if len(fileList) > len(w.Files) {
			// TODO: Return all new files?
			// Check for new files.
			var addedFile File
			for _, file := range fileList {
				if !fileInList(w.Files, file) {
					addedFile = file
				}
			}
			w.Event <- Event{EventType: EventFileAdded, File: addedFile}
			w.Files = fileList
		} else if len(fileList) < len(w.Files) {
			// TODO: Return all deleted files?
			//
			// Check for deleted files.
			var deletedFile File
			for _, file := range w.Files {
				if !fileInList(fileList, file) {
					deletedFile = file
				}
			}
			w.Event <- Event{EventType: EventFileDeleted, File: deletedFile}
			w.Files = fileList
		}

		// Check for modified files.
		for i, file := range w.Files {
			if fileList[i].ModTime() != file.ModTime() {
				w.Event <- Event{
					EventType: EventFileModified,
					File:      file,
				}
				w.Files = fileList
				break
			}
		}

		// Sleep for a little bit.
		time.Sleep(time.Millisecond * time.Duration(pollInterval))
	}

	return nil
}

// ListFiles returns a slice of all os.FileInfo's recursively
// contained in a directory. If name is a single file, it returns
// an os.FileInfo slice with a single os.FileInfo.
func ListFiles(name string) ([]File, error) {
	var currentDir string

	fileList := []File{}

	if err := filepath.Walk(name, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			currentDir = info.Name()
		}

		if err != nil {
			return err
		}

		fileList = append(fileList, File{Dir: currentDir, FileInfo: info})
		return nil
	}); err != nil {
		return nil, err
	}

	return fileList, nil
}

// fileInList checks whether or not a File exists in a []File.
func fileInList(fileList []File, file File) bool {
	for _, f := range fileList {
		if f.Dir == file.Dir && f.Name() == file.Name() {
			return true
		}
	}
	return false
}
<commit_msg>renamed trigger EventType parameter<commit_after>package watcher

import (
	"errors"
	"os"
	"path/filepath"
	"time"
)

var (
	// ErrNothingAdded is an error that occurs when a Watcher's Start() method is
	// called and no files or folders have been added to the Watcher's watchlist.
	ErrNothingAdded = errors.New("error: no files added to the watchlist")

	// ErrWatchedFileDeleted is an error that occurs when a file or folder that was
	// being watched has been deleted.
	ErrWatchedFileDeleted = errors.New("error: watched file or folder deleted")
)

// An EventType is a type that is used to describe what type
// of event has occured during the watching process.
type EventType int

const (
	EventFileAdded EventType = 1 << iota
	EventFileDeleted
	EventFileModified
)

// String returns a small string depending on what
// type of event it is.
func (e EventType) String() string {
	switch e {
	case EventFileAdded:
		return "FILE/FOLDER ADDED"
	case EventFileDeleted:
		return "FILE/FOLDER DELETED"
	case EventFileModified:
		return "FILE/FOLDER MODIFIED"
	default:
		return "UNRECOGNIZED EVENT"
	}
}

type Event struct {
	EventType
	File
}

// A Watcher describes a file watcher.
type Watcher struct {
	Names []string
	Files []File
	Event chan Event
	Error chan error
}

// A Watcher describes a file/folder being watched.
type File struct {
	Dir string
	os.FileInfo
}

// New returns a new initialized *Watcher.
func New() *Watcher {
	return &Watcher{
		Names: []string{},
		Files: []File{},
		Event: make(chan Event),
		Error: make(chan error),
	}
}

// fileInfo is an implementation of os.FileInfo that can be used
// as a mocked os.FileInfo when triggering an event when the specified
// File is nil.
type fileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	sys     interface{}
}

func (fs *fileInfo) IsDir() bool {
	return false
}
func (fs *fileInfo) ModTime() time.Time {
	return fs.modTime
}
func (fs *fileInfo) Mode() os.FileMode {
	return fs.mode
}
func (fs *fileInfo) Name() string {
	return fs.name
}
func (fs *fileInfo) Size() int64 {
	return fs.size
}
func (fs *fileInfo) Sys() interface{} {
	return fs.sys
}

// Trigger is a method that can be used to trigger an event, separate to
// the file watching process.
func (w *Watcher) Trigger(eventType EventType, file os.FileInfo) {
	if file == nil {
		file = &fileInfo{name: "triggered event", modTime: time.Now()}
	}
	w.Event <- Event{eventType, File{FileInfo: file}}
}

// Add adds either a single file or recursed directory to
// the Watcher's file list.
func (w *Watcher) Add(name string) error {
	// Add the name from w's Names list.
	w.Names = append(w.Names, name)

	// Make sure name exists.
	fInfo, err := os.Stat(name)
	if err != nil {
		return err
	}

	// If watching a single file, add it and return.
	if !fInfo.IsDir() {
		w.Files = append(w.Files, File{Dir: filepath.Dir(fInfo.Name()), FileInfo: fInfo})
		return nil
	}

	// Add all of the os.FileInfo's to w from dir recursively.
	fInfoList, err := ListFiles(name)
	if err != nil {
		return err
	}
	w.Files = append(w.Files, fInfoList...)
	return nil
}

// Remove removes either a single file or recursed directory from
// the Watcher's file list.
func (w *Watcher) Remove(name string) error {
	// Remove the name from w's Names list.
	for i := range w.Names {
		if w.Names[i] == name {
			w.Names = append(w.Names[:i], w.Names[i+1:]...)
		}
	}

	// Make sure name exists.
	fInfo, err := os.Stat(name)
	if err != nil {
		return err
	}

	// If name is a single file, remove it and return.
	if !fInfo.IsDir() {
		for i := range w.Files {
			if w.Files[i].FileInfo == fInfo &&
				w.Files[i].Dir == filepath.Dir(fInfo.Name()) {
				w.Files = append(w.Files[:i], w.Files[i+1:]...)
			}
		}
		return nil
	}

	// Retrieve a list of all of the os.FileInfo's to delete from w.Files.
	fileList, err := ListFiles(name)
	if err != nil {
		return err
	}

	// Remove the appropriate os.FileInfo's from w's os.FileInfo list.
	for _, file := range fileList {
		for i, wFile := range w.Files {
			if wFile.Dir == file.Dir &&
				wFile.Name() == file.Name() {
				w.Files = append(w.Files[:i], w.Files[i+1:]...)
			}
		}
	}
	return nil
}

// Start starts the watching process and checks for changes every `pollInterval`
// amount of milliseconds. If pollInterval is 0, the default is 100ms.
func (w *Watcher) Start(pollInterval int) error {
	if pollInterval == 0 {
		pollInterval = 100
	}

	if len(w.Names) < 1 {
		return ErrNothingAdded
	}

	for {
		var fileList []File
		for _, name := range w.Names {
			// Retrieve the list of os.FileInfo's from w.Name.
			list, err := ListFiles(name)
			if err != nil {
				if os.IsNotExist(err) {
					w.Error <- ErrWatchedFileDeleted
				} else {
					w.Error <- err
				}
			}
			fileList = append(fileList, list...)
		}

		if len(fileList) > len(w.Files) {
			// TODO: Return all new files?
			// Check for new files.
			var addedFile File
			for _, file := range fileList {
				if !fileInList(w.Files, file) {
					addedFile = file
				}
			}
			w.Event <- Event{EventType: EventFileAdded, File: addedFile}
			w.Files = fileList
		} else if len(fileList) < len(w.Files) {
			// TODO: Return all deleted files?
			//
			// Check for deleted files.
			var deletedFile File
			for _, file := range w.Files {
				if !fileInList(fileList, file) {
					deletedFile = file
				}
			}
			w.Event <- Event{EventType: EventFileDeleted, File: deletedFile}
			w.Files = fileList
		}

		// Check for modified files.
		for i, file := range w.Files {
			if fileList[i].ModTime() != file.ModTime() {
				w.Event <- Event{
					EventType: EventFileModified,
					File:      file,
				}
				w.Files = fileList
				break
			}
		}

		// Sleep for a little bit.
		time.Sleep(time.Millisecond * time.Duration(pollInterval))
	}

	return nil
}

// ListFiles returns a slice of all os.FileInfo's recursively
// contained in a directory. If name is a single file, it returns
// an os.FileInfo slice with a single os.FileInfo.
func ListFiles(name string) ([]File, error) {
	var currentDir string

	fileList := []File{}

	if err := filepath.Walk(name, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			currentDir = info.Name()
		}

		if err != nil {
			return err
		}

		fileList = append(fileList, File{Dir: currentDir, FileInfo: info})
		return nil
	}); err != nil {
		return nil, err
	}

	return fileList, nil
}

// fileInList checks whether or not a File exists in a []File.
func fileInList(fileList []File, file File) bool {
	for _, f := range fileList {
		if f.Dir == file.Dir && f.Name() == file.Name() {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2018 Capital One Services, LLC
//
// 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 (
	"context"
	"encoding/json"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/aws/signer/v4"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-xray-sdk-go/xray"
	"github.com/olivere/elastic"
	"github.com/sha1sum/aws_signing_client"
)

type cloudWatchEvent struct {
	Version    string    `json:"version"`
	ID         string    `json:"id"`
	DetailType string    `json:"detail-type"`
	Source     string    `json:"source"`
	AccountId  string    `json:"account"`
	Time       time.Time `json:"time"`
	Region     string    `json:"region"`
	Resources  []string  `json:"resources"`
	Detail     struct {
		RequestParameters struct {
			BucketName string
			Key        string
		}
	} `json:"detail"`
}

type myOutput struct {
	Tags map[string]string `yaml:"tags" json:"-"`
	processObj
	resourceObj
}

type tagObj struct {
	Key   string `json:"Key"`
	Value string `json:"Value"`
}

type processObj struct {
	Cmdline       string `json:"cmdline"`
	Rss           string `json:"rss"`
	CreateTime    string `json:"create_time"`
	WriteBytes    string `json:"write_bytes"`
	Name          string `json:"name"`
	Pid           string `json:"pid"`
	ThreadCount   string `json:"thread_count"`
	NumFds        string `json:"num_fds"`
	ReadBytes     string `json:"read_bytes"`
	User          string `json:"user"`
	Vms           string `json:"vms"`
	ResourceId    string `json:"resourceId"`
	CaptureTime   string `json:"captureTime"`
	SchemaVersion string `json:"schemaVersion"`
}

type resourceObj struct {
	KeyName      string `json:"KeyName"`
	AccountId    string `json:"AccountId"`
	Platform     string `json:"Platform"`
	InstanceId   string `json:"InstanceId"`
	VPCId        string `json:"VPCId"`
	State        string `json:"State"`
	ImageId      string `json:"ImageId"`
	InstanceRole string `json:"InstanceRole"`
	Region       string `json:"Region"`
	SubnetId     string `json:"SubnetId"`
	InstanceType string `json:"InstanceType"`
	Created      string `json:"Created"`
}

var (
	xRayTracingEnabled = os.Getenv("_X_AMZN_TRACE_ID")
	esClient           = os.Getenv("OMNISSM_ELASTIC_SEARCH_HTTP")
	indexName          = os.Getenv("OMNISSM_INDEX_NAME")
	typeName           = os.Getenv("OMNISSM_TYPE_NAME")
	requiredTags       = os.Getenv("OMNISSM_TAGS")
	s3Svc              = s3.New(session.New())
)

func main() {
	lambda.Start(func(ctx context.Context, event cloudWatchEvent) {
		if event.Source != "aws.s3" {
			return
		}
		if xRayTracingEnabled != "" {
			xray.AWS(s3Svc.Client)
		}
		if esClient == "" || indexName == "" || typeName == "" {
			log.Fatal("Missing required env variables OMNISSM_ELASTIC_SEARCH_HTTP, OMNISSM_INDEX_NAME, OMNISSM_TYPE_NAME")
		}

		var bucketName = event.Detail.RequestParameters.BucketName
		var bucketKey = event.Detail.RequestParameters.Key

		if bucketName == "" || bucketKey == "" {
			log.Fatal("Cloudwatch event missing BucketName or Key")
		}
		if !strings.Contains(bucketKey, "Custom:ProcessInfo") {
			return
		}

		client, err := newElasticClient(esClient)
		if err != nil {
			log.Fatal(err)
		}

		err = processEventRecord(ctx, bucketName, bucketKey, client)
		if err != nil {
			log.Fatal(err)
		}
	})
}

//get elastic client
func newElasticClient(url string) (*elastic.Client, error) {
	creds := credentials.NewEnvCredentials()
	signer := v4.NewSigner(creds)
	awsClient, err := aws_signing_client.New(signer, nil, "es", os.Getenv("AWS_REGION"))
	if err != nil {
		return nil, err
	}
	return elastic.NewClient(
		elastic.SetURL(url),
		elastic.SetScheme("https"),
		elastic.SetHttpClient(awsClient),
		elastic.SetSniff(false),
	)
}

func processEventRecord(ctx context.Context, bucketName string, bucketKey string, client *elastic.Client) error {
	//get filtered tags object
	tags, err := getTags(ctx, bucketName, bucketKey)
	if err != nil {
		return err
	}

	//get resource object
	resource, err := getResourceInfo(ctx, bucketName, bucketKey)
	if err != nil {
		return err
	}

	//get process file
	processFile, err := s3Svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(bucketKey),
	})
	if err != nil {
		return err
	}
	defer processFile.Body.Close()
	dec := json.NewDecoder(processFile.Body)

	for {
		var process processObj
		if err := dec.Decode(&process); err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		output := myOutput{
			Tags:        tags,
			resourceObj: resource,
			processObj:  process,
		}

		b, err := json.MarshalIndent(output, "", "  ")
		if err != nil {
			return err
		}

		_, err = client.Index().
			Index(indexName).
			Type(typeName).
			BodyJson(string(b)).
			Do(ctx)
		if err != nil {
			return err
		}
	}

	return nil
}

//used to flatten the struct sent to es
func (o myOutput) MarshalJSON() ([]byte, error) {

	type myOutput_ myOutput
	b, _ := json.Marshal(myOutput_(o))

	var m map[string]json.RawMessage
	json.Unmarshal(b, &m)

	for k, v := range o.Tags {
		b, _ = json.Marshal(v)
		m[k] = json.RawMessage(b)
	}

	return json.Marshal(m)
}

//Attempt to pull file from s3 with the same manager id, iterate over returned tags
func getTags(ctx context.Context, bucketName string, bucketKey string) (map[string]string, error) {
	tagsToGet := strings.Split(requiredTags, ",")
	tags := make(map[string]string)
	//get tags file from s3
	tagsRes, err := s3Svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(strings.Replace(bucketKey, "Custom:ProcessInfo", "AWS:Tag", 1)),
	})
	if err != nil {
		return tags, err
	}
	defer tagsRes.Body.Close()
	//setup decoder to iterate over individual tag objects
	dec := json.NewDecoder(tagsRes.Body)
	if err != nil {
		return tags, err
	}

	for {
		var aTagObj tagObj
		if err := dec.Decode(&aTagObj); err == io.EOF {
			break
		} else if err != nil {
			return tags, err
		}
		//search for specific tags
		for _, tag := range tagsToGet {
			if aTagObj.Key == tag {
				tags[aTagObj.Key] = aTagObj.Value
			}

		}
	}
	return tags, nil
}

func getResourceInfo(ctx context.Context, bucketName string, bucketKey string) (resourceObj, error) {
	var resource resourceObj
	//get resource file
	resourceFile, err := s3Svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(strings.Replace(bucketKey, "Custom:ProcessInfo", "Custom:CloudInfo", 1)),
	})

	if err != nil {
		return resource, err
	}
	defer resourceFile.Body.Close()

	resourceByteArray, err := ioutil.ReadAll(resourceFile.Body)
	if err != nil {
		return resource, err
	}

	err = json.Unmarshal(resourceByteArray, &resource)
	if err != nil {
		return resource, err
	}

	return resource, nil
}
<commit_msg>tools/omnissm - ess index use s3 notification relay -> sns -> sqs instead of cwe (#3009)<commit_after>// Copyright 2018 Capital One Services, LLC
//
// 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 (
	"context"
	"encoding/json"
	"io"
	"io/ioutil"
	"log"
	"net/url"
	"os"

	"strconv"
	"strings"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-xray-sdk-go/xray"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/aws/signer/v4"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/olivere/elastic"
	"github.com/sha1sum/aws_signing_client"
)

type snsEvent struct {
	Message          json.RawMessage
	Type             string
	MessageId        string
	TopicArn         string
	Subject          string
	Timestamp        string
	SignatureVersion string
	Signature        string
	SigningCertURL   string
	UnsubscribeURL   string
}

type record struct {
	Records []s3Event `json:"Records"`
}
type s3Event struct {
	AwsRegion   string `json:"awsRegion"`
	EventSource string `json:"eventSource"`
	EventTime   string `json:"eventTime"`
	S3          struct {
		Bucket struct {
			Name string
		}
		Object struct {
			Key string
		}
	} `json:"s3"`
}

type myOutput struct {
	Tags map[string]string `yaml:"tags" json:"-"`
	processObj
	resourceObj
}

type tagObj struct {
	Key   string `json:"Key"`
	Value string `json:"Value"`
}

type processObj struct {
	Cmdline       string `json:"cmdline"`
	Rss           string `json:"rss"`
	CreateTime    string `json:"create_time"`
	WriteBytes    string `json:"write_bytes"`
	Name          string `json:"name"`
	Pid           string `json:"pid"`
	ThreadCount   string `json:"thread_count"`
	NumFds        string `json:"num_fds"`
	ReadBytes     string `json:"read_bytes"`
	User          string `json:"user"`
	Vms           string `json:"vms"`
	ResourceId    string `json:"resourceId"`
	CaptureTime   string `json:"captureTime"`
	SchemaVersion string `json:"schemaVersion"`
}

type resourceObj struct {
	KeyName      string `json:"KeyName"`
	AccountId    string `json:"AccountId"`
	Platform     string `json:"Platform"`
	InstanceId   string `json:"InstanceId"`
	VPCId        string `json:"VPCId"`
	State        string `json:"State"`
	ImageId      string `json:"ImageId"`
	InstanceRole string `json:"InstanceRole"`
	Region       string `json:"Region"`
	SubnetId     string `json:"SubnetId"`
	InstanceType string `json:"InstanceType"`
	Created      string `json:"Created"`
}

var (
	xRayTracingEnabled = os.Getenv("_X_AMZN_TRACE_ID")
	esClient           = os.Getenv("OMNISSM_ELASTIC_SEARCH_HTTP")
	indexName          = os.Getenv("OMNISSM_INDEX_NAME")
	typeName           = os.Getenv("OMNISSM_TYPE_NAME")
	requiredTags       = os.Getenv("OMNISSM_TAGS")
	s3Svc              = s3.New(session.New())
)

func main() {
	lambda.Start(func(ctx context.Context, sqsEvent events.SQSEvent) {
		if xRayTracingEnabled != "" {
			xray.AWS(s3Svc.Client)
		}

		if esClient == "" || indexName == "" || typeName == "" {
			log.Fatal("Missing required env variables OMNISSM_ELASTIC_SEARCH_HTTP, OMNISSM_INDEX_NAME, OMNISSM_TYPE_NAME")
		}

		client, err := newElasticClient(esClient)
		if err != nil {
			log.Fatal(err)
		}

		for _, message := range sqsEvent.Records {
			var sns snsEvent
			json.Unmarshal([]byte(message.Body), &sns)
			var aRecord record
			s, err := strconv.Unquote(string(sns.Message))
			if err != nil {
				log.Fatal(err)
			}
			json.Unmarshal([]byte(s), &aRecord)
			for _, s3Event := range aRecord.Records {

				var bucketName = s3Event.S3.Bucket.Name
				bucketKey, err := url.QueryUnescape(s3Event.S3.Object.Key)
				if err != nil {
					log.Fatal(err)
				}

				if bucketName == "" || bucketKey == "" {
					log.Fatal("Event missing BucketName or Key")
				}

				err = processEventRecord(ctx, bucketName, bucketKey, client)
				if err != nil {
					log.Fatal(err)
				}
			}

		}

	})
}

//get elastic client
func newElasticClient(url string) (*elastic.Client, error) {
	creds := credentials.NewEnvCredentials()
	signer := v4.NewSigner(creds)
	awsClient, err := aws_signing_client.New(signer, nil, "es", os.Getenv("AWS_REGION"))
	if err != nil {
		return nil, err
	}
	return elastic.NewClient(
		elastic.SetURL(url),
		elastic.SetScheme("https"),
		elastic.SetHttpClient(awsClient),
		elastic.SetSniff(false),
	)
}

func processEventRecord(ctx context.Context, bucketName string, bucketKey string, client *elastic.Client) error {
	//get filtered tags object
	tags, err := getTags(ctx, bucketName, bucketKey)
	if err != nil {
		return err
	}

	//get resource object
	resource, err := getResourceInfo(ctx, bucketName, bucketKey)
	if err != nil {
		return err
	}

	//get process file
	processFile, err := s3Svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(bucketKey),
	})
	if err != nil {
		return err
	}
	defer processFile.Body.Close()
	dec := json.NewDecoder(processFile.Body)

	for {
		var process processObj
		if err := dec.Decode(&process); err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		output := myOutput{
			Tags:        tags,
			resourceObj: resource,
			processObj:  process,
		}

		b, err := json.MarshalIndent(output, "", "  ")
		if err != nil {
			return err
		}

		_, err = client.Index().
			Index(indexName).
			Type(typeName).
			BodyJson(string(b)).
			Do(ctx)
		if err != nil {
			return err
		}
	}

	return nil
}

//used to flatten the struct sent to es
func (o myOutput) MarshalJSON() ([]byte, error) {

	type myOutput_ myOutput
	b, _ := json.Marshal(myOutput_(o))

	var m map[string]json.RawMessage
	json.Unmarshal(b, &m)

	for k, v := range o.Tags {
		b, _ = json.Marshal(v)
		m[k] = json.RawMessage(b)
	}

	return json.Marshal(m)
}

//Attempt to pull file from s3 with the same manager id, iterate over returned tags
func getTags(ctx context.Context, bucketName string, bucketKey string) (map[string]string, error) {
	tagsToGet := strings.Split(requiredTags, ",")
	tags := make(map[string]string)
	//get tags file from s3
	tagsRes, err := s3Svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(strings.Replace(bucketKey, "Custom:ProcessInfo", "AWS:Tag", 1)),
	})
	if err != nil {
		return tags, err
	}
	defer tagsRes.Body.Close()
	//setup decoder to iterate over individual tag objects
	dec := json.NewDecoder(tagsRes.Body)
	if err != nil {
		return tags, err
	}

	for {
		var aTagObj tagObj
		if err := dec.Decode(&aTagObj); err == io.EOF {
			break
		} else if err != nil {
			return tags, err
		}
		//search for specific tags
		for _, tag := range tagsToGet {
			if aTagObj.Key == tag {
				tags[aTagObj.Key] = aTagObj.Value
			}

		}
	}
	return tags, nil
}

func getResourceInfo(ctx context.Context, bucketName string, bucketKey string) (resourceObj, error) {
	var resource resourceObj
	//get resource file
	resourceFile, err := s3Svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(strings.Replace(bucketKey, "Custom:ProcessInfo", "Custom:CloudInfo", 1)),
	})

	if err != nil {
		return resource, err
	}
	defer resourceFile.Body.Close()

	resourceByteArray, err := ioutil.ReadAll(resourceFile.Body)
	if err != nil {
		return resource, err
	}

	err = json.Unmarshal(resourceByteArray, &resource)
	if err != nil {
		return resource, err
	}

	return resource, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 James McGuire. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"

	irc "github.com/fluffle/goirc/client"
)

var directions = []string{"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}

const (
	weatherUpdateQuery   = `INSERT INTO weather_location (nick, location) VALUES (?, ?) ON DUPLICATE KEY UPDATE nick=?, location=?;`
	weatherLocationQuery = `SELECT location FROM weather_location where nick=?;`
	openweathermapURL    = `http://api.openweathermap.org/data/2.5/weather`
)

type owmData struct {
	Coord struct {
		Lon float64 `json:"lon"`
		Lat float64 `json:"lat"`
	} `json:"coord"`
	Weather []struct {
		ID          int    `json:"id"`
		Main        string `json:"main"`
		Description string `json:"description"`
		Icon        string `json:"icon"`
	} `json:"weather"`
	Base string `json:"base"`
	Main struct {
		Temp     float64 `json:"temp"`
		Pressure float64 `json:"pressure"`
		Humidity float64 `json:"humidity"`
		TempMin  float64 `json:"temp_min"`
		TempMax  float64 `json:"temp_max"`
	} `json:"main"`
	Wind struct {
		Speed float64 `json:"speed"`
		Deg   float64 `json:"deg"`
	} `json:"wind"`
	Clouds struct {
		All float64 `json:"all"`
	} `json:"clouds"`
	Dt  int `json:"dt"`
	Sys struct {
		Type    int     `json:"type"`
		ID      int     `json:"id"`
		Message float64 `json:"message"`
		Country string  `json:"country"`
		Sunrise int     `json:"sunrise"`
		Sunset  int     `json:"sunset"`
	} `json:"sys"`
	ID   int    `json:"id"`
	Name string `json:"name"`
	Cod  int    `json:"cod"`
}

func (o *owmData) String() string {
	conditions := []string{}
	for _, weather := range o.Weather {
		conditions = append(conditions, strings.Title(weather.Description))
	}
	weatherConds := strings.Join(conditions, ", ")
	tempC := o.Main.Temp - 273.15
	tempF := tempC*1.8 + 32.0
	windDir := getDirection(o.Wind.Deg)
	windSpeedMph := o.Wind.Speed * 2.23694
	windSpeedKph := o.Wind.Speed * 3.6
	return fmt.Sprintf("%s. %.1f °F / %.1f °C. Humidity %.0f%%. Wind from the %s at %.1f m/h / %.1f km/h. (%s)",
		weatherConds, tempF, tempC, o.Main.Humidity, windDir, windSpeedMph, windSpeedKph, o.Name)
}

func getDirection(deg float64) string {
	return directions[int(deg/22.5+.5)%16]
}

func fetchWeather(location string) (*owmData, error) {
	log.Printf("Querying openweathermap for %s", location)
	owm, err := url.Parse(openweathermapURL)
	if err != nil {
		return nil, err
	}
	v := owm.Query()
	v.Set("q", location)
	v.Set("APPID", config.OpenWeatherMapAPIKey)
	owm.RawQuery = v.Encode()
	resp, err := http.Get(owm.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	var owmdata owmData
	err = json.NewDecoder(resp.Body).Decode(&owmdata)
	if err != nil {
		return nil, err
	}
	log.Printf("%+v\n", owmdata)
	return &owmdata, nil
}

func findLocation(nick string) (string, error) {
	rows, err := db.Query(weatherLocationQuery, nick)
	if err != nil {
		return "", err
	}
	var location string
	for rows.Next() {
		if err := rows.Scan(&location); err != nil {
			return "", err
		}
	}
	return location, nil
}

func updateLocation(nick, location string) error {
	_, err := db.Exec(weatherUpdateQuery, nick, location, nick, location)
	if err != nil {
		return err
	}
	return nil
}

func showWeather(conn *irc.Conn, line *irc.Line) {
	if !strings.HasPrefix(line.Text(), "!w") {
		return
	}
	location := strings.TrimSpace(strings.TrimPrefix(line.Text(), "!w"))

	target_nick := line.Nick
	targeted := false

	switch {
	case strings.HasPrefix(location, "@"):
		target_nick = strings.TrimSpace(strings.TrimPrefix(location, "@"))
		location = ""
		targeted = true
	case strings.HasPrefix(location, "set "):
		location = strings.TrimSpace(strings.TrimPrefix(location, "set "))
		log.Printf("Updating location for %s to %s", line.Nick, location)
		err := updateLocation(line.Nick, location)
		if err != nil {
			log.Println("Error updating location:", err)
		}
		return
	case strings.HasPrefix(location, "help"):
		result := fmt.Sprintf("%s: Check the weather! set will set your location (!w set San Francisco, CA),"+
			" @ will show the weather for another nick (!w @sadbox), help will show this message.", line.Nick)
		conn.Privmsg(line.Target(), result)
		return
	}

	if location == "" || targeted {
		var err error
		location, err = findLocation(target_nick)
		if err != nil {
			log.Println("Error fetching location from DB:", err)
			return
		}
		if location == "" {
			result := ""
			if targeted {
				result = fmt.Sprintf("%s: %s hasn't ever set a location.", line.Nick, target_nick)
			} else {
				result = fmt.Sprintf("%s: You need to specify a location at least once. (!w set San Francisco, CA)", line.Nick)
			}
			conn.Privmsg(line.Target(), result)
			return
		}
	}

	weatherdata, err := fetchWeather(location)
	if err != nil {
		log.Println("Error fetching weather data...", err)
		return
	}
	result := fmt.Sprintf("%s: %s", line.Nick, weatherdata.String())
	conn.Privmsg(line.Target(), result)
}
<commit_msg>Weather updates<commit_after>// Copyright 2014 James McGuire. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"

	irc "github.com/fluffle/goirc/client"
)

var directions = []string{"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}

const (
	weatherUpdateQuery   = `INSERT INTO weather_location (nick, location) VALUES (?, ?) ON DUPLICATE KEY UPDATE nick=?, location=?;`
	weatherLocationQuery = `SELECT location FROM weather_location where nick=?;`
	openweathermapURL    = `http://api.openweathermap.org/data/2.5/weather`
)

type owmData struct {
	Coord struct {
		Lon float64 `json:"lon"`
		Lat float64 `json:"lat"`
	} `json:"coord"`
	Weather []struct {
		ID          int    `json:"id"`
		Main        string `json:"main"`
		Description string `json:"description"`
		Icon        string `json:"icon"`
	} `json:"weather"`
	Base string `json:"base"`
	Main struct {
		Temp     float64 `json:"temp"`
		Pressure float64 `json:"pressure"`
		Humidity float64 `json:"humidity"`
		TempMin  float64 `json:"temp_min"`
		TempMax  float64 `json:"temp_max"`
	} `json:"main"`
	Wind struct {
		Speed float64 `json:"speed"`
		Deg   float64 `json:"deg"`
	} `json:"wind"`
	Clouds struct {
		All float64 `json:"all"`
	} `json:"clouds"`
	Dt  int `json:"dt"`
	Sys struct {
		Type    int     `json:"type"`
		ID      int     `json:"id"`
		Message float64 `json:"message"`
		Country string  `json:"country"`
		Sunrise int     `json:"sunrise"`
		Sunset  int     `json:"sunset"`
	} `json:"sys"`
	ID   int    `json:"id"`
	Name string `json:"name"`
	Cod  int    `json:"cod"`
}

func (o *owmData) String() string {
	conditions := []string{}
	for _, weather := range o.Weather {
		conditions = append(conditions, strings.Title(weather.Description))
	}
	weatherConds := strings.Join(conditions, ", ")
	tempC := o.Main.Temp - 273.15
	tempF := tempC*1.8 + 32.0
	windDir := getDirection(o.Wind.Deg)
	windSpeedMph := o.Wind.Speed * 2.23694
	windSpeedKph := o.Wind.Speed * 3.6
	return fmt.Sprintf("%s. %.1f °F / %.1f °C. Humidity %.0f%%. Wind from the %s at %.1f m/h / %.1f km/h. (%s)",
		weatherConds, tempF, tempC, o.Main.Humidity, windDir, windSpeedMph, windSpeedKph, o.Name)
}

func getDirection(deg float64) string {
	return directions[int(deg/22.5+.5)%16]
}

func fetchWeather(location string) (*owmData, error) {
	log.Printf("Querying openweathermap for %s", location)
	owm, err := url.Parse(openweathermapURL)
	if err != nil {
		return nil, err
	}
	v := owm.Query()
	v.Set("q", location)
	v.Set("APPID", config.OpenWeatherMapAPIKey)
	owm.RawQuery = v.Encode()
	resp, err := http.Get(owm.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	var owmdata owmData
	err = json.NewDecoder(resp.Body).Decode(&owmdata)
	if err != nil {
		return nil, err
	}
	log.Printf("%+v\n", owmdata)
	return &owmdata, nil
}

func findLocation(nick string) (string, error) {
	rows, err := db.Query(weatherLocationQuery, nick)
	if err != nil {
		return "", err
	}
	var location string
	for rows.Next() {
		if err := rows.Scan(&location); err != nil {
			return "", err
		}
	}
	return location, nil
}

func updateLocation(nick, location string) error {
	_, err := db.Exec(weatherUpdateQuery, nick, location, nick, location)
	if err != nil {
		return err
	}
	return nil
}

func showWeather(conn *irc.Conn, line *irc.Line) {
	if !strings.HasPrefix(line.Text(), "!w") {
		return
	}
	location := strings.TrimSpace(strings.TrimPrefix(line.Text(), "!w"))

	target_nick := line.Nick
	targeted := false

	switch {
	case strings.HasPrefix(location, "@"):
		target_nick = strings.TrimSpace(strings.TrimPrefix(location, "@"))
		location = ""
		targeted = true
	case strings.HasPrefix(location, "set "):
		location = strings.TrimSpace(strings.TrimPrefix(location, "set "))
		log.Printf("Updating location for %s to %s", line.Nick, location)
		err := updateLocation(line.Nick, location)
		if err != nil {
			log.Println("Error updating location:", err)
		}
		result := fmt.Sprintf("%s: Your location has been updated to %s.", line.Nick, location)
		conn.Privmsg(line.Target(), result)
		return
	case strings.HasPrefix(location, "clear"):
		log.Printf("Clearing stored location for %s", line.Nick)
		err := updateLocation(line.Nick, "")
		if err != nil {
			log.Println("Error updating location:", err)
		}
		result := fmt.Sprintf("%s: Your location has been cleared in the database.", line.Nick)
		conn.Privmsg(line.Target(), result)
		return
	case strings.HasPrefix(location, "help"):
		result := fmt.Sprintf("%s: Check the weather! set will set your location (!w set San Francisco, CA),"+
			" clear will remove your stored location, @ will show the weather for another nick (!w @sadbox),"+
			" and help will show this message.", line.Nick)
		conn.Privmsg(line.Target(), result)
		return
	}

	if location == "" || targeted {
		var err error
		location, err = findLocation(target_nick)
		if err != nil {
			log.Println("Error fetching location from DB:", err)
			return
		}
		if location == "" {
			result := ""
			if targeted {
				result = fmt.Sprintf("%s: %s hasn't ever set a location.", line.Nick, target_nick)
			} else {
				result = fmt.Sprintf("%s: You need to specify a location at least once. (!w set San Francisco, CA)", line.Nick)
			}
			conn.Privmsg(line.Target(), result)
			return
		}
	}

	weatherdata, err := fetchWeather(location)
	if err != nil {
		result := fmt.Sprintf("%s: I can't seem to find anything for %s", line.Nick, location)
		conn.Privmsg(line.Target(), result)
		log.Println("Error fetching weather data...", err)
		return
	}
	result := fmt.Sprintf("%s: %s", line.Nick, weatherdata.String())
	conn.Privmsg(line.Target(), result)
}
<|endoftext|>


<commit_before>// +build run

package main

import (
	"github.com/zetamatta/nyagos/dos"
)

func main() {
	machines := []string{}

	err := dos.EachMachine(func(node *dos.NetResource) bool {
		machines = append(machines, node.RemoteName())
		return true
	})
	if err != nil {
		println(err.Error())
	}

	for _, name := range machines {
		println("machine:", name)
		err = dos.EachMachineNode(name, func(node *dos.NetResource) bool {
			println("  ", node.RemoteName())
			return true
		})
	}

	if err != nil {
		println(err.Error())
	}
}

// https://msdn.microsoft.com/ja-jp/library/cc447030.aspx
// http://eternalwindows.jp/security/share/share06.html
<commit_msg>Fix: broken example netresource_run.go<commit_after>// +build run

package main

import (
	"github.com/zetamatta/nyagos/dos"
)

func main() {
	machines := []string{}

	err := dos.EnumFileServer(func(node *dos.NetResource) bool {
		machines = append(machines, node.RemoteName())
		return true
	})
	if err != nil {
		println(err.Error())
	}

	for _, name := range machines {
		println("machine:", name)
		if fs,err := dos.NewFileServer(name) ; err == nil {
			fs.Enum(func(node *dos.NetResource) bool {
				println("  ", node.RemoteName())
				return true
			})
		}
	}

	if err != nil {
		println(err.Error())
	}
}

// https://msdn.microsoft.com/ja-jp/library/cc447030.aspx
// http://eternalwindows.jp/security/share/share06.html
<|endoftext|>