<commit_before>package brontide

import (
	"errors"
	"fmt"
	"io"
	"net"
	"time"

	"github.com/btcsuite/btcd/btcec"
)

// defaultHandshakes is the maximum number of handshakes that can be done in
// parallel.
const defaultHandshakes = 1000

// Listener is an implementation of a net.Conn which executes an authenticated
// key exchange and message encryption protocol dubbed "Machine" after
// initial connection acceptance. See the Machine struct for additional
// details w.r.t the handshake and encryption scheme used within the
// connection.
type Listener struct {
	localStatic *btcec.PrivateKey

	tcp *net.TCPListener

	handshakeSema chan struct{}
	conns         chan maybeConn
	quit          chan struct{}
}

// A compile-time assertion to ensure that Conn meets the net.Listener interface.
var _ net.Listener = (*Listener)(nil)

// NewListener returns a new net.Listener which enforces the Brontide scheme
// during both initial connection establishment and data transfer.
func NewListener(localStatic *btcec.PrivateKey, listenAddr string) (*Listener,
	error) {
	addr, err := net.ResolveTCPAddr("tcp", listenAddr)
	if err != nil {
		return nil, err
	}

	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return nil, err
	}

	brontideListener := &Listener{
		localStatic:   localStatic,
		tcp:           l,
		handshakeSema: make(chan struct{}, defaultHandshakes),
		conns:         make(chan maybeConn),
		quit:          make(chan struct{}),
	}

	for i := 0; i < defaultHandshakes; i++ {
		brontideListener.handshakeSema <- struct{}{}
	}

	go brontideListener.listen()

	return brontideListener, nil
}

// listen accepts connection from the underlying tcp conn, then performs
// the brontinde handshake procedure asynchronously. A maximum of
// defaultHandshakes will be active at any given time.
//
// NOTE: This method must be run as a goroutine.
func (l *Listener) listen() {
	for {
		select {
		case <-l.handshakeSema:
		case <-l.quit:
			return
		}

		conn, err := l.tcp.Accept()
		if err != nil {
			l.rejectConn(err)
			l.handshakeSema <- struct{}{}
			continue
		}

		go l.doHandshake(conn)
	}
}

// rejectedConnErr is a helper function that prepends the remote address of the
// failed connection attempt to the original error message.
func rejectedConnErr(err error, remoteAddr string) error {
	return fmt.Errorf("unable to accept connection from %v: %v", remoteAddr,
		err)
}

// doHandshake asynchronously performs the brontide handshake, so that it does
// not block the main accept loop. This prevents peers that delay writing to the
// connection from block other connection attempts.
func (l *Listener) doHandshake(conn net.Conn) {
	defer func() { l.handshakeSema <- struct{}{} }()

	select {
	case <-l.quit:
		return
	default:
	}

	remoteAddr := conn.RemoteAddr().String()

	brontideConn := &Conn{
		conn:  conn,
		noise: NewBrontideMachine(false, l.localStatic, nil),
	}

	// We'll ensure that we get ActOne from the remote peer in a timely
	// manner. If they don't respond within 1s, then we'll kill the
	// connection.
	conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))

	// Attempt to carry out the first act of the handshake protocol. If the
	// connecting node doesn't know our long-term static public key, then
	// this portion will fail with a non-nil error.
	var actOne [ActOneSize]byte
	if _, err := io.ReadFull(conn, actOne[:]); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}
	if err := brontideConn.noise.RecvActOne(actOne); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	// Next, progress the handshake processes by sending over our ephemeral
	// key for the session along with an authenticating tag.
	actTwo, err := brontideConn.noise.GenActTwo()
	if err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}
	if _, err := conn.Write(actTwo[:]); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	select {
	case <-l.quit:
		return
	default:
	}

	// We'll ensure that we get ActTwo from the remote peer in a timely
	// manner. If they don't respond within 1 second, then we'll kill the
	// connection.
	conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))

	// Finally, finish the handshake processes by reading and decrypting
	// the connection peer's static public key. If this succeeds then both
	// sides have mutually authenticated each other.
	var actThree [ActThreeSize]byte
	if _, err := io.ReadFull(conn, actThree[:]); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}
	if err := brontideConn.noise.RecvActThree(actThree); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	// We'll reset the deadline as it's no longer critical beyond the
	// initial handshake.
	conn.SetReadDeadline(time.Time{})

	l.acceptConn(brontideConn)
}

// maybeConn holds either a brontide connection or an error returned from the
// handshake.
type maybeConn struct {
	conn *Conn
	err  error
}

// acceptConn returns a connection that successfully performed a handshake.
func (l *Listener) acceptConn(conn *Conn) {
	select {
	case l.conns <- maybeConn{conn: conn}:
	case <-l.quit:
	}
}

// rejectConn returns any errors encountered during connection or handshake.
func (l *Listener) rejectConn(err error) {
	select {
	case l.conns <- maybeConn{err: err}:
	case <-l.quit:
	}
}

// Accept waits for and returns the next connection to the listener. All
// incoming connections are authenticated via the three act Brontide
// key-exchange scheme. This function will fail with a non-nil error in the
// case that either the handshake breaks down, or the remote peer doesn't know
// our static public key.
//
// Part of the net.Listener interface.
func (l *Listener) Accept() (net.Conn, error) {
	select {
	case result := <-l.conns:
		return result.conn, result.err
	case <-l.quit:
		return nil, errors.New("brontide connection closed")
	}
}

// Close closes the listener.  Any blocked Accept operations will be unblocked
// and return errors.
//
// Part of the net.Listener interface.
func (l *Listener) Close() error {
	select {
	case <-l.quit:
	default:
		close(l.quit)
	}

	return l.tcp.Close()
}

// Addr returns the listener's network address.
//
// Part of the net.Listener interface.
func (l *Listener) Addr() net.Addr {
	return l.tcp.Addr()
}
<commit_msg>brontide/listener: handle SetReadDeadline errors<commit_after>package brontide

import (
	"errors"
	"fmt"
	"io"
	"net"
	"time"

	"github.com/btcsuite/btcd/btcec"
)

// defaultHandshakes is the maximum number of handshakes that can be done in
// parallel.
const defaultHandshakes = 1000

// Listener is an implementation of a net.Conn which executes an authenticated
// key exchange and message encryption protocol dubbed "Machine" after
// initial connection acceptance. See the Machine struct for additional
// details w.r.t the handshake and encryption scheme used within the
// connection.
type Listener struct {
	localStatic *btcec.PrivateKey

	tcp *net.TCPListener

	handshakeSema chan struct{}
	conns         chan maybeConn
	quit          chan struct{}
}

// A compile-time assertion to ensure that Conn meets the net.Listener interface.
var _ net.Listener = (*Listener)(nil)

// NewListener returns a new net.Listener which enforces the Brontide scheme
// during both initial connection establishment and data transfer.
func NewListener(localStatic *btcec.PrivateKey, listenAddr string) (*Listener,
	error) {
	addr, err := net.ResolveTCPAddr("tcp", listenAddr)
	if err != nil {
		return nil, err
	}

	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return nil, err
	}

	brontideListener := &Listener{
		localStatic:   localStatic,
		tcp:           l,
		handshakeSema: make(chan struct{}, defaultHandshakes),
		conns:         make(chan maybeConn),
		quit:          make(chan struct{}),
	}

	for i := 0; i < defaultHandshakes; i++ {
		brontideListener.handshakeSema <- struct{}{}
	}

	go brontideListener.listen()

	return brontideListener, nil
}

// listen accepts connection from the underlying tcp conn, then performs
// the brontinde handshake procedure asynchronously. A maximum of
// defaultHandshakes will be active at any given time.
//
// NOTE: This method must be run as a goroutine.
func (l *Listener) listen() {
	for {
		select {
		case <-l.handshakeSema:
		case <-l.quit:
			return
		}

		conn, err := l.tcp.Accept()
		if err != nil {
			l.rejectConn(err)
			l.handshakeSema <- struct{}{}
			continue
		}

		go l.doHandshake(conn)
	}
}

// rejectedConnErr is a helper function that prepends the remote address of the
// failed connection attempt to the original error message.
func rejectedConnErr(err error, remoteAddr string) error {
	return fmt.Errorf("unable to accept connection from %v: %v", remoteAddr,
		err)
}

// doHandshake asynchronously performs the brontide handshake, so that it does
// not block the main accept loop. This prevents peers that delay writing to the
// connection from block other connection attempts.
func (l *Listener) doHandshake(conn net.Conn) {
	defer func() { l.handshakeSema <- struct{}{} }()

	select {
	case <-l.quit:
		return
	default:
	}

	remoteAddr := conn.RemoteAddr().String()

	brontideConn := &Conn{
		conn:  conn,
		noise: NewBrontideMachine(false, l.localStatic, nil),
	}

	// We'll ensure that we get ActOne from the remote peer in a timely
	// manner. If they don't respond within 1s, then we'll kill the
	// connection.
	err := conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
	if err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	// Attempt to carry out the first act of the handshake protocol. If the
	// connecting node doesn't know our long-term static public key, then
	// this portion will fail with a non-nil error.
	var actOne [ActOneSize]byte
	if _, err := io.ReadFull(conn, actOne[:]); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}
	if err := brontideConn.noise.RecvActOne(actOne); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	// Next, progress the handshake processes by sending over our ephemeral
	// key for the session along with an authenticating tag.
	actTwo, err := brontideConn.noise.GenActTwo()
	if err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}
	if _, err := conn.Write(actTwo[:]); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	select {
	case <-l.quit:
		return
	default:
	}

	// We'll ensure that we get ActTwo from the remote peer in a timely
	// manner. If they don't respond within 1 second, then we'll kill the
	// connection.
	err = conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
	if err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	// Finally, finish the handshake processes by reading and decrypting
	// the connection peer's static public key. If this succeeds then both
	// sides have mutually authenticated each other.
	var actThree [ActThreeSize]byte
	if _, err := io.ReadFull(conn, actThree[:]); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}
	if err := brontideConn.noise.RecvActThree(actThree); err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	// We'll reset the deadline as it's no longer critical beyond the
	// initial handshake.
	err = conn.SetReadDeadline(time.Time{})
	if err != nil {
		brontideConn.conn.Close()
		l.rejectConn(rejectedConnErr(err, remoteAddr))
		return
	}

	l.acceptConn(brontideConn)
}

// maybeConn holds either a brontide connection or an error returned from the
// handshake.
type maybeConn struct {
	conn *Conn
	err  error
}

// acceptConn returns a connection that successfully performed a handshake.
func (l *Listener) acceptConn(conn *Conn) {
	select {
	case l.conns <- maybeConn{conn: conn}:
	case <-l.quit:
	}
}

// rejectConn returns any errors encountered during connection or handshake.
func (l *Listener) rejectConn(err error) {
	select {
	case l.conns <- maybeConn{err: err}:
	case <-l.quit:
	}
}

// Accept waits for and returns the next connection to the listener. All
// incoming connections are authenticated via the three act Brontide
// key-exchange scheme. This function will fail with a non-nil error in the
// case that either the handshake breaks down, or the remote peer doesn't know
// our static public key.
//
// Part of the net.Listener interface.
func (l *Listener) Accept() (net.Conn, error) {
	select {
	case result := <-l.conns:
		return result.conn, result.err
	case <-l.quit:
		return nil, errors.New("brontide connection closed")
	}
}

// Close closes the listener.  Any blocked Accept operations will be unblocked
// and return errors.
//
// Part of the net.Listener interface.
func (l *Listener) Close() error {
	select {
	case <-l.quit:
	default:
		close(l.quit)
	}

	return l.tcp.Close()
}

// Addr returns the listener's network address.
//
// Part of the net.Listener interface.
func (l *Listener) Addr() net.Addr {
	return l.tcp.Addr()
}
<|endoftext|>


<commit_before>package ethpub

import (
	"encoding/hex"
	"encoding/json"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethutil"
	_ "log"
	"strings"
)

// Block interface exposed to QML
type PBlock struct {
	ref          *ethchain.Block
	Number       int    `json:"number"`
	Hash         string `json:"hash"`
	Transactions string `json:"transactions"`
	Time         int64  `json:"time"`
}

// Creates a new QML Block from a chain block
func NewPBlock(block *ethchain.Block) *PBlock {
	if block == nil {
		return nil
	}

	var ptxs []PTx
	for _, tx := range block.Transactions() {
		ptxs = append(ptxs, *NewPTx(tx))
	}

	txJson, err := json.Marshal(ptxs)
	if err != nil {
		return nil
	}

	return &PBlock{ref: block, Number: int(block.Number.Uint64()), Hash: ethutil.Hex(block.Hash()), Transactions: string(txJson), Time: block.Time}
}

func (self *PBlock) ToString() string {
	if self.ref != nil {
		return self.ref.String()
	}

	return ""
}

func (self *PBlock) GetTransaction(hash string) *PTx {
	tx := self.ref.GetTransaction(ethutil.FromHex(hash))
	if tx == nil {
		return nil
	}

	return NewPTx(tx)
}

type PTx struct {
	ref *ethchain.Transaction

	Value           string `json:"value"`
	Gas             string `json:"gas"`
	GasPrice        string `json:"gasPrice"`
	Hash            string `json:"hash"`
	Address         string `json:"address"`
	Sender          string `json:"sender"`
	RawData         string `json:"rawData"`
	Data            string `json:"data"`
	Contract        bool   `json:"isContract"`
	CreatesContract bool   `json:"createsContract"`
}

func NewPTx(tx *ethchain.Transaction) *PTx {
	hash := hex.EncodeToString(tx.Hash())
	receiver := hex.EncodeToString(tx.Recipient)

	if receiver == "" {
		receiver = hex.EncodeToString(tx.CreationAddress())
	}
	sender := hex.EncodeToString(tx.Sender())
	createsContract := tx.CreatesContract()

	data := strings.Join(ethchain.Disassemble(tx.Data), "\n")

	isContract := len(tx.Data) > 0

	return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: isContract, Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: hex.EncodeToString(tx.Data)}
}

func (self *PTx) ToString() string {
	return self.ref.String()
}

type PKey struct {
	Address    string `json:"address"`
	PrivateKey string `json:"privateKey"`
	PublicKey  string `json:"publicKey"`
}

func NewPKey(key *ethutil.KeyPair) *PKey {
	return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)}
}

type PReceipt struct {
	CreatedContract bool   `json:"createdContract"`
	Address         string `json:"address"`
	Hash            string `json:"hash"`
	Sender          string `json:"sender"`
}

func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt {
	return &PReceipt{
		contractCreation,
		ethutil.Hex(creationAddress),
		ethutil.Hex(hash),
		ethutil.Hex(address),
	}
}

type PStateObject struct {
	object *ethchain.StateObject
}

func NewPStateObject(object *ethchain.StateObject) *PStateObject {
	return &PStateObject{object: object}
}

func (c *PStateObject) GetStorage(address string) string {
	// Because somehow, even if you return nil to QML it
	// still has some magical object so we can't rely on
	// undefined or null at the QML side
	if c.object != nil {
		val := c.object.GetMem(ethutil.Big("0x" + address))

		return val.BigInt().String()
	}

	return ""
}

func (c *PStateObject) Value() string {
	if c.object != nil {
		return c.object.Amount.String()
	}

	return ""
}

func (c *PStateObject) Address() string {
	if c.object != nil {
		return ethutil.Hex(c.object.Address())
	}

	return ""
}

func (c *PStateObject) Nonce() int {
	if c.object != nil {
		return int(c.object.Nonce)
	}

	return 0
}

func (c *PStateObject) Root() string {
	if c.object != nil {
		return ethutil.Hex(ethutil.NewValue(c.object.State().Root()).Bytes())
	}

	return "<err>"
}

func (c *PStateObject) IsContract() bool {
	if c.object != nil {
		return len(c.object.Script()) > 0
	}

	return false
}

func (c *PStateObject) Script() string {
	if c.object != nil {
		return strings.Join(ethchain.Disassemble(c.object.Script()), " ")
	}

	return ""
}

type PStorageState struct {
	StateAddress string
	Address      string
	Value        string
}

func NewPStorageState(storageObject *ethchain.StorageState) *PStorageState {
	return &PStorageState{ethutil.Hex(storageObject.StateAddress), ethutil.Hex(storageObject.Address), storageObject.Value.String()}
}
<commit_msg>Added coin base to pub block<commit_after>package ethpub

import (
	"encoding/hex"
	"encoding/json"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethutil"
	_ "log"
	"strings"
)

// Block interface exposed to QML
type PBlock struct {
	ref          *ethchain.Block
	Number       int    `json:"number"`
	Hash         string `json:"hash"`
	Transactions string `json:"transactions"`
	Time         int64  `json:"time"`
	Coinbase     string `json:"coinbase"`
}

// Creates a new QML Block from a chain block
func NewPBlock(block *ethchain.Block) *PBlock {
	if block == nil {
		return nil
	}

	var ptxs []PTx
	for _, tx := range block.Transactions() {
		ptxs = append(ptxs, *NewPTx(tx))
	}

	txJson, err := json.Marshal(ptxs)
	if err != nil {
		return nil
	}

	return &PBlock{ref: block, Number: int(block.Number.Uint64()), Hash: ethutil.Hex(block.Hash()), Transactions: string(txJson), Time: block.Time, Coinbase: ethutil.Hex(block.Coinbase)}
}

func (self *PBlock) ToString() string {
	if self.ref != nil {
		return self.ref.String()
	}

	return ""
}

func (self *PBlock) GetTransaction(hash string) *PTx {
	tx := self.ref.GetTransaction(ethutil.FromHex(hash))
	if tx == nil {
		return nil
	}

	return NewPTx(tx)
}

type PTx struct {
	ref *ethchain.Transaction

	Value           string `json:"value"`
	Gas             string `json:"gas"`
	GasPrice        string `json:"gasPrice"`
	Hash            string `json:"hash"`
	Address         string `json:"address"`
	Sender          string `json:"sender"`
	RawData         string `json:"rawData"`
	Data            string `json:"data"`
	Contract        bool   `json:"isContract"`
	CreatesContract bool   `json:"createsContract"`
}

func NewPTx(tx *ethchain.Transaction) *PTx {
	hash := hex.EncodeToString(tx.Hash())
	receiver := hex.EncodeToString(tx.Recipient)

	if receiver == "" {
		receiver = hex.EncodeToString(tx.CreationAddress())
	}
	sender := hex.EncodeToString(tx.Sender())
	createsContract := tx.CreatesContract()

	data := strings.Join(ethchain.Disassemble(tx.Data), "\n")

	isContract := len(tx.Data) > 0

	return &PTx{ref: tx, Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: receiver, Contract: isContract, Gas: tx.Gas.String(), GasPrice: tx.GasPrice.String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: hex.EncodeToString(tx.Data)}
}

func (self *PTx) ToString() string {
	return self.ref.String()
}

type PKey struct {
	Address    string `json:"address"`
	PrivateKey string `json:"privateKey"`
	PublicKey  string `json:"publicKey"`
}

func NewPKey(key *ethutil.KeyPair) *PKey {
	return &PKey{ethutil.Hex(key.Address()), ethutil.Hex(key.PrivateKey), ethutil.Hex(key.PublicKey)}
}

type PReceipt struct {
	CreatedContract bool   `json:"createdContract"`
	Address         string `json:"address"`
	Hash            string `json:"hash"`
	Sender          string `json:"sender"`
}

func NewPReciept(contractCreation bool, creationAddress, hash, address []byte) *PReceipt {
	return &PReceipt{
		contractCreation,
		ethutil.Hex(creationAddress),
		ethutil.Hex(hash),
		ethutil.Hex(address),
	}
}

type PStateObject struct {
	object *ethchain.StateObject
}

func NewPStateObject(object *ethchain.StateObject) *PStateObject {
	return &PStateObject{object: object}
}

func (c *PStateObject) GetStorage(address string) string {
	// Because somehow, even if you return nil to QML it
	// still has some magical object so we can't rely on
	// undefined or null at the QML side
	if c.object != nil {
		val := c.object.GetMem(ethutil.Big("0x" + address))

		return val.BigInt().String()
	}

	return ""
}

func (c *PStateObject) Value() string {
	if c.object != nil {
		return c.object.Amount.String()
	}

	return ""
}

func (c *PStateObject) Address() string {
	if c.object != nil {
		return ethutil.Hex(c.object.Address())
	}

	return ""
}

func (c *PStateObject) Nonce() int {
	if c.object != nil {
		return int(c.object.Nonce)
	}

	return 0
}

func (c *PStateObject) Root() string {
	if c.object != nil {
		return ethutil.Hex(ethutil.NewValue(c.object.State().Root()).Bytes())
	}

	return "<err>"
}

func (c *PStateObject) IsContract() bool {
	if c.object != nil {
		return len(c.object.Script()) > 0
	}

	return false
}

func (c *PStateObject) Script() string {
	if c.object != nil {
		return strings.Join(ethchain.Disassemble(c.object.Script()), " ")
	}

	return ""
}

type PStorageState struct {
	StateAddress string
	Address      string
	Value        string
}

func NewPStorageState(storageObject *ethchain.StorageState) *PStorageState {
	return &PStorageState{ethutil.Hex(storageObject.StateAddress), ethutil.Hex(storageObject.Address), storageObject.Value.String()}
}
<|endoftext|>


<commit_before>// The `s3` plugin for SHIELD is intended to be a back-end storage
// plugin, wrapping Amazon's Simple Storage Service (S3). It should
// be compatible with other services which emulate the S3 API, offering
// similar storage solutions for private cloud offerings (such as OpenStack
// Swift). However, this plugin has only been tested with Amazon S3.
//
// PLUGIN FEATURES
//
// This plugin implements functionality suitable for use with the following
// SHIELD Job components:
//
//  Target: no
//  Store:  yes
//
// PLUGIN CONFIGURATION
//
// The endpoint configuration passed to this plugin is used to determine
// how to connect to S3, and where to place/retrieve the data once connected.
// your endpoint JSON should look something like this:
//
//    {
//        "s3_host":             "s3.amazonaws.com", # default
//        "access_key_id":       "your-access-key-id",
//        "secret_access_key":   "your-secret-access-key",
//        "skip_ssl_validation":  false,
//        "bucket":              "bucket-name",
//        "prefix":              "/path/inside/bucket/to/place/backup/data",
//        "signature_version":   "4",  # should be 2 or 4. Defaults to 4
//        "socks5_proxy":        ""    # optionally defined SOCKS5 proxy to use for the s3 communications
//    }
//
// `prefix` will default to the empty string, and backups will be placed in the
// root of the bucket.
//
// STORE DETAILS
//
// When storing data, this plugin connects to the S3 service, and uploads the data
// into the specified bucket, using a path/filename with the following format:
//
//    <prefix>/<YYYY>/<MM>/<DD>/<HH-mm-SS>-<UUID>
//
// Upon successful storage, the plugin then returns this filename to SHIELD to use
// as the `store_key` when the data needs to be retrieved, or purged.
//
// RETRIEVE DETAILS
//
// When retrieving data, this plugin connects to the S3 service, and retrieves the data
// located in the specified bucket, identified by the `store_key` provided by SHIELD.
//
// PURGE DETAILS
//
// When purging data, this plugin connects to the S3 service, and deletes the data
// located in the specified bucket, identified by the `store_key` provided by SHIELD.
//
// DEPENDENCIES
//
// None.
//
package main

import (
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	minio "github.com/minio/minio-go"
	"github.com/starkandwayne/goutils/ansi"
	"golang.org/x/net/proxy"

	"github.com/starkandwayne/shield/plugin"
)

const (
	DefaultS3Host            = "s3.amazonaws.com"
	DefaultPrefix            = ""
	DefaultSigVersion        = "4"
	DefaultSkipSSLValidation = false
)

func validSigVersion(v string) bool {
	return v == "2" || v == "4"
}

func main() {
	p := S3Plugin{
		Name:    "S3 Backup + Storage Plugin",
		Author:  "Stark & Wayne",
		Version: "0.0.1",
		Features: plugin.PluginFeatures{
			Target: "no",
			Store:  "yes",
		},
	}

	plugin.Run(p)
}

type S3Plugin plugin.PluginInfo

type S3ConnectionInfo struct {
	Host              string
	SkipSSLValidation bool
	AccessKey         string
	SecretKey         string
	Bucket            string
	PathPrefix        string
	SignatureVersion  string
	SOCKS5Proxy       string
}

func (p S3Plugin) Meta() plugin.PluginInfo {
	return plugin.PluginInfo(p)
}

func (p S3Plugin) Validate(endpoint plugin.ShieldEndpoint) error {
	var (
		s    string
		err  error
		fail bool
	)

	s, err = endpoint.StringValueDefault("s3_host", DefaultS3Host)
	if err != nil {
		ansi.Printf("@R{\u2717 s3_host              %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 s3_host}              @C{%s}\n", s)
	}

	s, err = endpoint.StringValue("access_key_id")
	if err != nil {
		ansi.Printf("@R{\u2717 access_key_id        %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 access_key_id}        @C{%s}\n", s)
	}

	s, err = endpoint.StringValue("secret_access_key")
	if err != nil {
		ansi.Printf("@R{\u2717 secret_access_key    %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 secret_access_key}    @C{%s}\n", s)
	}

	s, err = endpoint.StringValue("bucket")
	if err != nil {
		ansi.Printf("@R{\u2717 bucket               %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 bucket}               @C{%s}\n", s)
	}

	s, err = endpoint.StringValueDefault("prefix", DefaultPrefix)
	if err != nil {
		ansi.Printf("@R{\u2717 prefix               %s}\n", err)
		fail = true
	} else if s == "" {
		ansi.Printf("@G{\u2713 prefix}               (none)\n")
	} else {
		ansi.Printf("@G{\u2713 prefix}               @C{%s}\n", s)
	}

	s, err = endpoint.StringValueDefault("signature_version", DefaultSigVersion)
	if err != nil {
		ansi.Printf("@R{\u2717 signature_version    %s}\n", err)
		fail = true
	} else if !validSigVersion(s) {
		ansi.Printf("@R{\u2717 signature_version    Unexpected signature version '%s' found (expecting '2' or '4')}\n", s)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 signature_version}    @C{%s}\n", s)
	}

	s, err = endpoint.StringValueDefault("socks5_proxy", "")
	if err != nil {
		ansi.Printf("@R{\u2717 socks5_proxy         %s}\n", err)
		fail = true
	} else if s == "" {
		ansi.Printf("@G{\u2713 socks5_proxy}         (no proxy will be used)\n")
	} else {
		ansi.Printf("@G{\u2713 socks5_proxy}         @C{%s}\n", s)
	}

	tf, err := endpoint.BooleanValueDefault("skip_ssl_validation", DefaultSkipSSLValidation)
	if err != nil {
		ansi.Printf("@R{\u2717 skip_ssl_validation  %s}\n", err)
		fail = true
	} else if tf {
		ansi.Printf("@G{\u2713 skip_ssl_validation}  @C{yes}, SSL will @Y{NOT} be validated\n")
	} else {
		ansi.Printf("@G{\u2713 skip_ssl_validation}  @C{no}, SSL @Y{WILL} be validated\n")
	}

	if fail {
		return fmt.Errorf("s3: invalid configuration")
	}
	return nil
}

func (p S3Plugin) Backup(endpoint plugin.ShieldEndpoint) error {
	return plugin.UNIMPLEMENTED
}

func (p S3Plugin) Restore(endpoint plugin.ShieldEndpoint) error {
	return plugin.UNIMPLEMENTED
}

func (p S3Plugin) Store(endpoint plugin.ShieldEndpoint) (string, error) {
	s3, err := getS3ConnInfo(endpoint)
	if err != nil {
		return "", err
	}
	client, err := s3.Connect()
	if err != nil {
		return "", err
	}

	path := s3.genBackupPath()
	plugin.DEBUG("Storing data in %s", path)

	// FIXME: should we do something with the size of the write performed?
	_, err = client.PutObject(s3.Bucket, path, os.Stdin, "application/x-gzip")
	if err != nil {
		return "", err
	}

	return path, nil
}

func (p S3Plugin) Retrieve(endpoint plugin.ShieldEndpoint, file string) error {
	s3, err := getS3ConnInfo(endpoint)
	if err != nil {
		return err
	}
	client, err := s3.Connect()
	if err != nil {
		return err
	}

	reader, err := client.GetObject(s3.Bucket, file)
	if err != nil {
		return err
	}
	if _, err = io.Copy(os.Stdout, reader); err != nil {
		return err
	}

	err = reader.Close()
	if err != nil {
		return err
	}

	return nil
}

func (p S3Plugin) Purge(endpoint plugin.ShieldEndpoint, file string) error {
	s3, err := getS3ConnInfo(endpoint)
	if err != nil {
		return err
	}
	client, err := s3.Connect()
	if err != nil {
		return err
	}

	err = client.RemoveObject(s3.Bucket, file)
	if err != nil {
		return err
	}

	return nil
}

func getS3ConnInfo(e plugin.ShieldEndpoint) (S3ConnectionInfo, error) {
	host, err := e.StringValueDefault("s3_host", DefaultS3Host)
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	insecure_ssl, err := e.BooleanValueDefault("skip_ssl_validation", DefaultSkipSSLValidation)
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	key, err := e.StringValue("access_key_id")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	secret, err := e.StringValue("secret_access_key")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	bucket, err := e.StringValue("bucket")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	prefix, err := e.StringValueDefault("prefix", DefaultPrefix)
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	sigVer, err := e.StringValueDefault("signature_version", DefaultSigVersion)
	if !validSigVersion(sigVer) {
		return S3ConnectionInfo{}, fmt.Errorf("Invalid `signature_version` specified (`%s`). Expected `2` or `4`", sigVer)
	}

	proxy, err := e.StringValueDefault("socks5_proxy", "")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	return S3ConnectionInfo{
		Host:              host,
		SkipSSLValidation: insecure_ssl,
		AccessKey:         key,
		SecretKey:         secret,
		Bucket:            bucket,
		PathPrefix:        prefix,
		SignatureVersion:  sigVer,
		SOCKS5Proxy:       proxy,
	}, nil
}

func (s3 S3ConnectionInfo) genBackupPath() string {
	t := time.Now()
	year, mon, day := t.Date()
	hour, min, sec := t.Clock()
	uuid := plugin.GenUUID()
	path := fmt.Sprintf("%s/%04d/%02d/%02d/%04d-%02d-%02d-%02d%02d%02d-%s", s3.PathPrefix, year, mon, day, year, mon, day, hour, min, sec, uuid)
	path = strings.Replace(path, "//", "/", -1)
	return path
}

func (s3 S3ConnectionInfo) Connect() (*minio.Client, error) {
	var s3Client *minio.Client
	var err error
	if s3.SignatureVersion == "2" {
		s3Client, err = minio.NewV2(s3.Host, s3.AccessKey, s3.SecretKey, false)
	} else {
		s3Client, err = minio.NewV4(s3.Host, s3.AccessKey, s3.SecretKey, false)
	}
	if err != nil {
		return nil, err
	}

	transport := http.DefaultTransport
	transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: s3.SkipSSLValidation}
	if s3.SOCKS5Proxy != "" {
		dialer, err := proxy.SOCKS5("tcp", s3.SOCKS5Proxy, nil, proxy.Direct)
		if err != nil {
			fmt.Fprintln(os.Stderr, "can't connect to the proxy:", err)
			os.Exit(1)
		}
		transport.(*http.Transport).Dial = dialer.Dial
	}

	s3Client.SetCustomTransport(transport)

	return s3Client, nil
}
<commit_msg>remove the leading slash if there is one<commit_after>// The `s3` plugin for SHIELD is intended to be a back-end storage
// plugin, wrapping Amazon's Simple Storage Service (S3). It should
// be compatible with other services which emulate the S3 API, offering
// similar storage solutions for private cloud offerings (such as OpenStack
// Swift). However, this plugin has only been tested with Amazon S3.
//
// PLUGIN FEATURES
//
// This plugin implements functionality suitable for use with the following
// SHIELD Job components:
//
//  Target: no
//  Store:  yes
//
// PLUGIN CONFIGURATION
//
// The endpoint configuration passed to this plugin is used to determine
// how to connect to S3, and where to place/retrieve the data once connected.
// your endpoint JSON should look something like this:
//
//    {
//        "s3_host":             "s3.amazonaws.com", # default
//        "access_key_id":       "your-access-key-id",
//        "secret_access_key":   "your-secret-access-key",
//        "skip_ssl_validation":  false,
//        "bucket":              "bucket-name",
//        "prefix":              "/path/inside/bucket/to/place/backup/data",
//        "signature_version":   "4",  # should be 2 or 4. Defaults to 4
//        "socks5_proxy":        ""    # optionally defined SOCKS5 proxy to use for the s3 communications
//    }
//
// `prefix` will default to the empty string, and backups will be placed in the
// root of the bucket.
//
// STORE DETAILS
//
// When storing data, this plugin connects to the S3 service, and uploads the data
// into the specified bucket, using a path/filename with the following format:
//
//    <prefix>/<YYYY>/<MM>/<DD>/<HH-mm-SS>-<UUID>
//
// Upon successful storage, the plugin then returns this filename to SHIELD to use
// as the `store_key` when the data needs to be retrieved, or purged.
//
// RETRIEVE DETAILS
//
// When retrieving data, this plugin connects to the S3 service, and retrieves the data
// located in the specified bucket, identified by the `store_key` provided by SHIELD.
//
// PURGE DETAILS
//
// When purging data, this plugin connects to the S3 service, and deletes the data
// located in the specified bucket, identified by the `store_key` provided by SHIELD.
//
// DEPENDENCIES
//
// None.
//
package main

import (
	"crypto/tls"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	minio "github.com/minio/minio-go"
	"github.com/starkandwayne/goutils/ansi"
	"golang.org/x/net/proxy"

	"github.com/starkandwayne/shield/plugin"
)

const (
	DefaultS3Host            = "s3.amazonaws.com"
	DefaultPrefix            = ""
	DefaultSigVersion        = "4"
	DefaultSkipSSLValidation = false
)

func validSigVersion(v string) bool {
	return v == "2" || v == "4"
}

func main() {
	p := S3Plugin{
		Name:    "S3 Backup + Storage Plugin",
		Author:  "Stark & Wayne",
		Version: "0.0.1",
		Features: plugin.PluginFeatures{
			Target: "no",
			Store:  "yes",
		},
	}

	plugin.Run(p)
}

type S3Plugin plugin.PluginInfo

type S3ConnectionInfo struct {
	Host              string
	SkipSSLValidation bool
	AccessKey         string
	SecretKey         string
	Bucket            string
	PathPrefix        string
	SignatureVersion  string
	SOCKS5Proxy       string
}

func (p S3Plugin) Meta() plugin.PluginInfo {
	return plugin.PluginInfo(p)
}

func (p S3Plugin) Validate(endpoint plugin.ShieldEndpoint) error {
	var (
		s    string
		err  error
		fail bool
	)

	s, err = endpoint.StringValueDefault("s3_host", DefaultS3Host)
	if err != nil {
		ansi.Printf("@R{\u2717 s3_host              %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 s3_host}              @C{%s}\n", s)
	}

	s, err = endpoint.StringValue("access_key_id")
	if err != nil {
		ansi.Printf("@R{\u2717 access_key_id        %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 access_key_id}        @C{%s}\n", s)
	}

	s, err = endpoint.StringValue("secret_access_key")
	if err != nil {
		ansi.Printf("@R{\u2717 secret_access_key    %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 secret_access_key}    @C{%s}\n", s)
	}

	s, err = endpoint.StringValue("bucket")
	if err != nil {
		ansi.Printf("@R{\u2717 bucket               %s}\n", err)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 bucket}               @C{%s}\n", s)
	}

	s, err = endpoint.StringValueDefault("prefix", DefaultPrefix)
	if err != nil {
		ansi.Printf("@R{\u2717 prefix               %s}\n", err)
		fail = true
	} else if s == "" {
		ansi.Printf("@G{\u2713 prefix}               (none)\n")
	} else {
		ansi.Printf("@G{\u2713 prefix}               @C{%s}\n", s)
	}

	s, err = endpoint.StringValueDefault("signature_version", DefaultSigVersion)
	if err != nil {
		ansi.Printf("@R{\u2717 signature_version    %s}\n", err)
		fail = true
	} else if !validSigVersion(s) {
		ansi.Printf("@R{\u2717 signature_version    Unexpected signature version '%s' found (expecting '2' or '4')}\n", s)
		fail = true
	} else {
		ansi.Printf("@G{\u2713 signature_version}    @C{%s}\n", s)
	}

	s, err = endpoint.StringValueDefault("socks5_proxy", "")
	if err != nil {
		ansi.Printf("@R{\u2717 socks5_proxy         %s}\n", err)
		fail = true
	} else if s == "" {
		ansi.Printf("@G{\u2713 socks5_proxy}         (no proxy will be used)\n")
	} else {
		ansi.Printf("@G{\u2713 socks5_proxy}         @C{%s}\n", s)
	}

	tf, err := endpoint.BooleanValueDefault("skip_ssl_validation", DefaultSkipSSLValidation)
	if err != nil {
		ansi.Printf("@R{\u2717 skip_ssl_validation  %s}\n", err)
		fail = true
	} else if tf {
		ansi.Printf("@G{\u2713 skip_ssl_validation}  @C{yes}, SSL will @Y{NOT} be validated\n")
	} else {
		ansi.Printf("@G{\u2713 skip_ssl_validation}  @C{no}, SSL @Y{WILL} be validated\n")
	}

	if fail {
		return fmt.Errorf("s3: invalid configuration")
	}
	return nil
}

func (p S3Plugin) Backup(endpoint plugin.ShieldEndpoint) error {
	return plugin.UNIMPLEMENTED
}

func (p S3Plugin) Restore(endpoint plugin.ShieldEndpoint) error {
	return plugin.UNIMPLEMENTED
}

func (p S3Plugin) Store(endpoint plugin.ShieldEndpoint) (string, error) {
	s3, err := getS3ConnInfo(endpoint)
	if err != nil {
		return "", err
	}
	client, err := s3.Connect()
	if err != nil {
		return "", err
	}

	path := s3.genBackupPath()
	plugin.DEBUG("Storing data in %s", path)

	// FIXME: should we do something with the size of the write performed?
	_, err = client.PutObject(s3.Bucket, path, os.Stdin, "application/x-gzip")
	if err != nil {
		return "", err
	}

	return path, nil
}

func (p S3Plugin) Retrieve(endpoint plugin.ShieldEndpoint, file string) error {
	s3, err := getS3ConnInfo(endpoint)
	if err != nil {
		return err
	}
	client, err := s3.Connect()
	if err != nil {
		return err
	}

	reader, err := client.GetObject(s3.Bucket, file)
	if err != nil {
		return err
	}
	if _, err = io.Copy(os.Stdout, reader); err != nil {
		return err
	}

	err = reader.Close()
	if err != nil {
		return err
	}

	return nil
}

func (p S3Plugin) Purge(endpoint plugin.ShieldEndpoint, file string) error {
	s3, err := getS3ConnInfo(endpoint)
	if err != nil {
		return err
	}
	client, err := s3.Connect()
	if err != nil {
		return err
	}

	err = client.RemoveObject(s3.Bucket, file)
	if err != nil {
		return err
	}

	return nil
}

func getS3ConnInfo(e plugin.ShieldEndpoint) (S3ConnectionInfo, error) {
	host, err := e.StringValueDefault("s3_host", DefaultS3Host)
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	insecure_ssl, err := e.BooleanValueDefault("skip_ssl_validation", DefaultSkipSSLValidation)
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	key, err := e.StringValue("access_key_id")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	secret, err := e.StringValue("secret_access_key")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	bucket, err := e.StringValue("bucket")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	prefix, err := e.StringValueDefault("prefix", DefaultPrefix)
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	sigVer, err := e.StringValueDefault("signature_version", DefaultSigVersion)
	if !validSigVersion(sigVer) {
		return S3ConnectionInfo{}, fmt.Errorf("Invalid `signature_version` specified (`%s`). Expected `2` or `4`", sigVer)
	}

	proxy, err := e.StringValueDefault("socks5_proxy", "")
	if err != nil {
		return S3ConnectionInfo{}, err
	}

	return S3ConnectionInfo{
		Host:              host,
		SkipSSLValidation: insecure_ssl,
		AccessKey:         key,
		SecretKey:         secret,
		Bucket:            bucket,
		PathPrefix:        prefix,
		SignatureVersion:  sigVer,
		SOCKS5Proxy:       proxy,
	}, nil
}

func (s3 S3ConnectionInfo) genBackupPath() string {
	t := time.Now()
	year, mon, day := t.Date()
	hour, min, sec := t.Clock()
	uuid := plugin.GenUUID()
	path := fmt.Sprintf("%s/%04d/%02d/%02d/%04d-%02d-%02d-%02d%02d%02d-%s", s3.PathPrefix, year, mon, day, year, mon, day, hour, min, sec, uuid)
	// Remove double slashes
	path = strings.Replace(path, "//", "/", -1)
	// Remove a leading slash
	if strings.HasPrefix(path, "/") {
		strings.Replace(path, "/", "", 1))
	}
	return path
}

func (s3 S3ConnectionInfo) Connect() (*minio.Client, error) {
	var s3Client *minio.Client
	var err error
	if s3.SignatureVersion == "2" {
		s3Client, err = minio.NewV2(s3.Host, s3.AccessKey, s3.SecretKey, false)
	} else {
		s3Client, err = minio.NewV4(s3.Host, s3.AccessKey, s3.SecretKey, false)
	}
	if err != nil {
		return nil, err
	}

	transport := http.DefaultTransport
	transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: s3.SkipSSLValidation}
	if s3.SOCKS5Proxy != "" {
		dialer, err := proxy.SOCKS5("tcp", s3.SOCKS5Proxy, nil, proxy.Direct)
		if err != nil {
			fmt.Fprintln(os.Stderr, "can't connect to the proxy:", err)
			os.Exit(1)
		}
		transport.(*http.Transport).Dial = dialer.Dial
	}

	s3Client.SetCustomTransport(transport)

	return s3Client, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/corywalker/expreduce/expreduce"
	"gopkg.in/readline.v1"
)

func main() {
	var debug = flag.Bool("debug", false, "Debug mode. No initial definitions.")
	flag.Parse()

	rl, err := readline.NewEx(&readline.Config{
		HistoryFile:         "/tmp/readline.tmp",
		ForceUseInteractive: true,
	})
	if err != nil {
		panic(err)
	}
	defer rl.Close()

	es := expreduce.NewEvalState()
	if *debug {
		es.NoInit = true
		es.ClearAll()
	}

	fmt.Printf("Welcome to Expreduce!\n\n")
	promptNum := 1
	for {
		rl.SetPrompt(fmt.Sprintf("In[%d]:= ", promptNum))
		line, err := rl.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		if line == "" {
			continue
		}
		fmt.Printf("\n")

		exp := expreduce.Interp(line)
		res := exp.Eval(es)

		isNull := false
		asSym, isSym := res.(*expreduce.Symbol)
		if isSym {
			if asSym.Name == "Null" {
				isNull = true
			}
		}

		if !isNull {
			// Print formatted result
			specialForms := []string{
				"FullForm",
				"OutputForm",
			}
			wasSpecialForm := false
			for _, specialForm := range specialForms {
				asSpecialForm, isSpecialForm := expreduce.HeadAssertion(res, specialForm)
				if !isSpecialForm {
					continue
				}
				if len(asSpecialForm.Parts) != 2 {
					continue
				}
				fmt.Printf(
					"Out[%d]//%s= %s\n\n",
					promptNum,
					specialForm,
					asSpecialForm.Parts[1].StringForm(specialForm),
				)
				wasSpecialForm = true
			}
			if !wasSpecialForm {
				fmt.Printf("Out[%d]= %s\n\n", promptNum, res.StringForm("InputForm"))
			}
		}

		promptNum += 1
	}
}
<commit_msg>Ability to profile interactive session.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"runtime/pprof"
	"log"
	"github.com/corywalker/expreduce/expreduce"
	"gopkg.in/readline.v1"
)

var debug = flag.Bool("debug", false, "Debug mode. No initial definitions.")
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	rl, err := readline.NewEx(&readline.Config{
		HistoryFile:         "/tmp/readline.tmp",
		ForceUseInteractive: true,
	})
	if err != nil {
		panic(err)
	}
	defer rl.Close()

	es := expreduce.NewEvalState()
	if *debug {
		es.NoInit = true
		es.ClearAll()
	}

	fmt.Printf("Welcome to Expreduce!\n\n")
	promptNum := 1
	for {
		rl.SetPrompt(fmt.Sprintf("In[%d]:= ", promptNum))
		line, err := rl.Readline()
		if err != nil { // io.EOF, readline.ErrInterrupt
			break
		}
		if line == "" {
			continue
		}
		fmt.Printf("\n")

		exp := expreduce.Interp(line)
		res := exp.Eval(es)

		isNull := false
		asSym, isSym := res.(*expreduce.Symbol)
		if isSym {
			if asSym.Name == "Null" {
				isNull = true
			}
		}

		if !isNull {
			// Print formatted result
			specialForms := []string{
				"FullForm",
				"OutputForm",
			}
			wasSpecialForm := false
			for _, specialForm := range specialForms {
				asSpecialForm, isSpecialForm := expreduce.HeadAssertion(res, specialForm)
				if !isSpecialForm {
					continue
				}
				if len(asSpecialForm.Parts) != 2 {
					continue
				}
				fmt.Printf(
					"Out[%d]//%s= %s\n\n",
					promptNum,
					specialForm,
					asSpecialForm.Parts[1].StringForm(specialForm),
				)
				wasSpecialForm = true
			}
			if !wasSpecialForm {
				fmt.Printf("Out[%d]= %s\n\n", promptNum, res.StringForm("InputForm"))
			}
		}

		promptNum += 1
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/alce/conekta"
	"log"
)

var client *conekta.Client

func init() {
	// To test on a sandbox account, set CONEKTA_API_KEY environment variable
	// os.Setenv("CONEKTA_API_KEY", "THE_KEY")
	client = conekta.NewClient()

	// To test on local server, uncomment to set the base url:
	// u, _ := url.Parse("http://localhost:3000")
	// client.BaseURL(u)
}

func main() {
	createAndUpdateCustomer()
	createCardCharge()
	createPlan()
}

func createAndUpdateCustomer() {
	// Create a customer
	c := &conekta.Customer{
		Name:  "Logan",
		Email: "no@email.com",
		Phone: "222-333-444",
	}

	customer, err := client.Customers.Create(c)
	if err != nil {
		log.Println(err)
	}
	log.Println(customer.Name)

	// Update the customer
	customer.Name = "Xavier"
	updatedCustomer, err := client.Customers.Update(customer.Id, customer)
	if err != nil {
		log.Println(err)
	}
	log.Println(updatedCustomer.Name)
}

func createCardCharge() {
	c := &conekta.Charge{
		Description: "Stogies",
		Amount:      20000,
		Currency:    "MXN",
		ReferenceId: "9839-wolf_pack",
		Card:        "tok_test_visa_4242",
	}

	charge, err := client.Charges.Create(c)
	if err != nil {
		log.Println(err)
	}

	log.Println(charge)
}

func createPlan() {
	p := &conekta.Plan{
		Name: "Golden Boy",
		Amount: 333333,
	}

	plan, err := client.Plans.Create(p)
	if err != nil {
		log.Println(err)
	}

	log.Println(plan)
}
<commit_msg>update import paths<commit_after>package main

import (
	"github.com/Boletia/conekta"
	"log"
)

var client *conekta.Client

func init() {
	client = conekta.NewClient()
}

func main() {
	createAndUpdateCustomer()
	createCardCharge()
	createPlan()
}

func createAndUpdateCustomer() {
	// Create a customer
	c := &conekta.Customer{
		Name:  "Logan",
		Email: "no@email.com",
		Phone: "222-333-444",
	}

	customer, err := client.Customers.Create(c)
	if err != nil {
		log.Println(err)
	}
	log.Println(customer.Name)

	// Update the customer
	customer.Name = "Xavier"
	updatedCustomer, err := client.Customers.Update(customer.Id, customer)
	if err != nil {
		log.Println(err)
	}
	log.Println(updatedCustomer.Name)
}

func createCardCharge() {
	c := &conekta.Charge{
		Description: "Stogies",
		Amount:      20000,
		Currency:    "MXN",
		ReferenceId: "9839-wolf_pack",
		Card:        "tok_test_visa_4242",
	}

	charge, err := client.Charges.Create(c)
	if err != nil {
		log.Println(err)
	}

	log.Println(charge)
}

func createPlan() {
	p := &conekta.Plan{
		Name: "Golden Boy",
		Amount: 333333,
	}

	plan, err := client.Plans.Create(p)
	if err != nil {
		log.Println(err)
	}

	log.Println(plan)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/karlseguin/garnish"
	"github.com/karlseguin/garnish/gc"
	"time"
)

func main() {
	config := garnish.Configure().Address("127.0.0.1:8080").Debug()
	config.Hydrate(HydrateLoader)
	config.Stats().FileName("stats.json").Slow(time.Millisecond * 100)
	config.Cache().Grace(time.Minute).PurgeHandler(PurgeHandler)
	config.Upstream("test").Address("http://localhost:3000").KeepAlive(8)
	config.Route("users").Get("/v1/queue").Upstream("test").CacheTTL(time.Minute)
	runtime, err := config.Build()
	fmt.Println(runtime.Cache.Load("cache.save"))
	if err != nil {
		panic(err)
	}
	go garnish.Start(runtime)
	time.Sleep(time.Second * 10)
	fmt.Println(runtime.Cache.Save("cache.save", 10, time.Second*10))
}

func HydrateLoader(fragment gc.ReferenceFragment) []byte {
	return []byte(`{"id": "hyd-` + fragment.String("id") + `"}`)
}

func PurgeHandler(req *gc.Request, lookup gc.CacheKeyLookup, cache gc.CacheStorage) gc.Response {
	primary, secondary := lookup(req)
	if cache.Delete(primary, secondary) {
		return gc.PurgeHitResponse
	}
	return gc.PurgeMissResponse
}
<commit_msg>cleaned up example<commit_after>package main

import (
	"github.com/karlseguin/garnish"
	"github.com/karlseguin/garnish/gc"
	"time"
)

func main() {
	config := garnish.Configure().Address("127.0.0.1:8080").Debug()
	config.Hydrate(HydrateLoader)
	config.Stats().FileName("stats.json").Slow(time.Millisecond * 100)
	config.Cache().Grace(time.Minute).PurgeHandler(PurgeHandler)
	config.Upstream("test").Address("http://localhost:3000").KeepAlive(8)
	config.Route("users").Get("/v1/users").Upstream("test").CacheTTL(time.Minute)
	runtime, err := config.Build()
	if err != nil {
		panic(err)
	}
	garnish.Start(runtime)
}

func HydrateLoader(fragment gc.ReferenceFragment) []byte {
	return []byte(`{"id": "hyd-` + fragment.String("id") + `"}`)
}

func PurgeHandler(req *gc.Request, lookup gc.CacheKeyLookup, cache gc.CacheStorage) gc.Response {
	primary, secondary := lookup(req)
	if cache.Delete(primary, secondary) {
		return gc.PurgeHitResponse
	}
	return gc.PurgeMissResponse
}
<|endoftext|>


<commit_before>// Copyright 2019 Google 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"
	"errors"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"time"

	stackdriver "github.com/google/go-metrics-stackdriver"

	"cloud.google.com/go/compute/metadata"
	monitoring "cloud.google.com/go/monitoring/apiv3"
	metrics "github.com/armon/go-metrics"
)

func main() {
	// setup client
	ctx, cancel := context.WithCancel(context.Background())
	client, err := monitoring.NewMetricClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")

	if projectID == "" {
		if projectID, err = metadata.ProjectID(); err != nil {
			log.Fatal(err)
		}
	}

	log.Printf("initializing sink, project_id: %q", projectID)

	// create sink
	ss := stackdriver.NewSink(client, &stackdriver.Config{
		ProjectID:         projectID,
		Location:          "us-east1-c",
		DebugLogs:         true,
		ReportingInterval: 35 * time.Second,
	})
	defer ss.Close(context.Background())

	cfg := metrics.DefaultConfig("go-metrics-stackdriver")
	cfg.EnableHostname = false
	metrics.NewGlobal(cfg, ss)

	// start listener
	log.Printf("starting server")
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		defer metrics.MeasureSince([]string{"handler"}, time.Now())
		metrics.IncrCounter([]string{"requests"}, 1.0)
		fmt.Fprintf(w, "Hello from go-metrics-stackdriver")
	})

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	srv := http.Server{
		Addr: ":" + port,
	}
	go func() {
		if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			log.Printf("server error: %s", err)
		}
	}()

	// capture ctrl+c
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		log.Printf("ctrl+c detected... shutting down")
		cancel()
		srv.Shutdown(context.Background())
	}()

	// generate data
	log.Printf("sending data")
	exercise(ctx, ss)
}

func exercise(ctx context.Context, m metrics.MetricSink) {
	for {
		select {
		case <-time.After(100 * time.Millisecond):
			m.SetGauge([]string{"foo"}, 42)
			m.IncrCounter([]string{"baz"}, 1)
			m.AddSample([]string{"method", "rand"}, 500*rand.Float32())
			m.AddSample([]string{"method", "const"}, 200)
			m.AddSample([]string{"method", "dist"}, 50)
			m.AddSample([]string{"method", "dist"}, 100)
			m.AddSample([]string{"method", "dist"}, 150)
			m.AddSample([]string{"foo"}, 100)
		case <-ctx.Done():
			log.Printf("terminating")
			return
		}
	}
}
<commit_msg>remove features incompatible with go1.12<commit_after>// Copyright 2019 Google 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"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"time"

	stackdriver "github.com/google/go-metrics-stackdriver"

	"cloud.google.com/go/compute/metadata"
	monitoring "cloud.google.com/go/monitoring/apiv3"
	metrics "github.com/armon/go-metrics"
)

func main() {
	// setup client
	ctx, cancel := context.WithCancel(context.Background())
	client, err := monitoring.NewMetricClient(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")

	if projectID == "" {
		if projectID, err = metadata.ProjectID(); err != nil {
			log.Fatal(err)
		}
	}

	log.Printf("initializing sink, project_id: %q", projectID)

	// create sink
	ss := stackdriver.NewSink(client, &stackdriver.Config{
		ProjectID:         projectID,
		Location:          "us-east1-c",
		DebugLogs:         true,
		ReportingInterval: 35 * time.Second,
	})
	defer ss.Close(context.Background())

	cfg := metrics.DefaultConfig("go-metrics-stackdriver")
	cfg.EnableHostname = false
	metrics.NewGlobal(cfg, ss)

	// start listener
	log.Printf("starting server")
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		defer metrics.MeasureSince([]string{"handler"}, time.Now())
		metrics.IncrCounter([]string{"requests"}, 1.0)
		fmt.Fprintf(w, "Hello from go-metrics-stackdriver")
	})

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	srv := http.Server{
		Addr: ":" + port,
	}
	go func() {
		if err := srv.ListenAndServe(); err != nil {
			log.Printf("server error: %s", err)
		}
	}()

	// capture ctrl+c
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		log.Printf("ctrl+c detected... shutting down")
		cancel()
		srv.Shutdown(context.Background())
	}()

	// generate data
	log.Printf("sending data")
	exercise(ctx, ss)
}

func exercise(ctx context.Context, m metrics.MetricSink) {
	for {
		select {
		case <-time.After(100 * time.Millisecond):
			m.SetGauge([]string{"foo"}, 42)
			m.IncrCounter([]string{"baz"}, 1)
			m.AddSample([]string{"method", "rand"}, 500*rand.Float32())
			m.AddSample([]string{"method", "const"}, 200)
			m.AddSample([]string{"method", "dist"}, 50)
			m.AddSample([]string{"method", "dist"}, 100)
			m.AddSample([]string{"method", "dist"}, 150)
			m.AddSample([]string{"foo"}, 100)
		case <-ctx.Done():
			log.Printf("terminating")
			return
		}
	}
}
<|endoftext|>


<commit_before>package plugins

import (
	"errors"
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"

	"github.com/ArjenSchwarz/igor/config"
	"github.com/ArjenSchwarz/igor/slack"
)

// RememberPlugin provides remember functions
type RememberPlugin struct {
	name        string
	description string
	request     slack.Request
	config      rememberConfig
}

// Remember instantiates the RememberPlugin
func Remember(request slack.Request) (IgorPlugin, error) {
	pluginName := "remember"
	pluginConfig, err := parseRememberConfig()
	if err != nil {
		return RememberPlugin{}, err
	}
	pluginConfig.languages = getPluginLanguages(pluginName)
	plugin := RememberPlugin{
		name:    pluginName,
		request: request,
		config:  pluginConfig,
	}

	return plugin, nil
}

// Work parses the request and ensures a request comes through if any triggers
// are matched. Handled triggers:
//
//  * remember
//  * remember2
func (plugin RememberPlugin) Work() (slack.Response, error) {
	response := slack.Response{}
	if plugin.config.Dynamodb == "" {
		return response, errors.New("No DynamoDB configured")
	}
	message, language := getCommandName(plugin)
	plugin.config.chosenLanguage = language
	switch message {
	case "remember":
		tmpresponse, err := plugin.handleRemember(response)
		if err != nil {
			return tmpresponse, err
		}
		response = tmpresponse
	case "show":
		return plugin.handleShow(response)
	case "forget":
		return plugin.handleForget(response)
	case "showall":
		return plugin.handleShowAll(response)
	}
	if response.Text == "" {
		return response, CreateNoMatchError("Nothing found")
	}
	return response, nil
}

// Describe provides the triggers RememberPlugin can handle
func (plugin RememberPlugin) Describe(language string) map[string]string {
	descriptions := make(map[string]string)
	if plugin.config.Dynamodb == "" {
		return descriptions
	}
	for commandName, values := range getAllCommands(plugin, language) {
		if commandName != "forget" || plugin.request.UserInList(plugin.config.Admins) {
			descriptions[values.Command] = values.Description
		}
	}
	return descriptions
}

func (plugin RememberPlugin) handleRemember(response slack.Response) (slack.Response, error) {
	commandDetails := getCommandDetails(plugin, "remember")
	if plugin.request.UserInList(plugin.config.Blacklist) {
		response.Text = commandDetails.Texts["forbidden"]
		return response, nil
	}
	parts := strings.Split(plugin.Message(), " ")
	name := strings.TrimSpace(parts[1])
	url := strings.TrimSpace(parts[2])

	response.Text = strings.Replace(commandDetails.Texts["response_text"], "[replace]", name, 1)
	sess, err := session.NewSession()
	if err != nil {
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.PutItemInput{
		Item: map[string]*dynamodb.AttributeValue{
			"name": {S: aws.String(name)},
			"url":  {S: aws.String(url)},
			"user": {S: aws.String(plugin.request.UserName)},
		},
		TableName: aws.String(plugin.config.Dynamodb),
	}
	_, err = svc.PutItem(params)

	return response, err
}

func (plugin RememberPlugin) handleForget(response slack.Response) (slack.Response, error) {
	commandDetails := getCommandDetails(plugin, "forget")
	if !plugin.request.UserInList(plugin.config.Admins) {
		response.Text = commandDetails.Texts["forbidden"]
		return response, nil
	}
	parts := strings.Split(plugin.Message(), " ")
	name := strings.TrimSpace(parts[1])

	response.Text = strings.Replace(commandDetails.Texts["response_text"], "[replace]", name, 1)
	sess, err := session.NewSession()
	if err != nil {
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.DeleteItemInput{
		Key: map[string]*dynamodb.AttributeValue{ // Required
			"name": {S: aws.String(name)},
		},
		TableName: aws.String(plugin.config.Dynamodb), // Required
	}
	_, err = svc.DeleteItem(params)
	return response, err
}

func (plugin RememberPlugin) handleShow(response slack.Response) (slack.Response, error) {
	var subject string
	commandDetails := getCommandDetails(plugin, "show")
	parts := strings.Split(plugin.Message(), " ")
	subject = strings.TrimSpace(strings.Replace(plugin.Message(), parts[0], "", 1))

	sess, err := session.NewSession()
	if err != nil {
		fmt.Println("failed to create session,", err)
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.GetItemInput{
		Key: map[string]*dynamodb.AttributeValue{
			"name": {S: aws.String(subject)},
		},
		TableName: aws.String(plugin.config.Dynamodb),
	}
	resp, err := svc.GetItem(params)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "ResourceNotFoundException" {
				response.Text = commandDetails.Texts["no_result"]
				return response, nil
			}
		}
		return response, err
	}

	response.Text = aws.StringValue(resp.Item["name"].S)
	attach := slack.Attachment{
		ImageURL: aws.StringValue(resp.Item["url"].S),
	}
	response.AddAttachment(attach)
	response.SetPublic()
	return response, nil
}

func (plugin RememberPlugin) handleShowAll(response slack.Response) (slack.Response, error) {
	commandDetails := getCommandDetails(plugin, "showall")
	sess, err := session.NewSession()
	if err != nil {
		fmt.Println("failed to create session,", err)
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.ScanInput{
		TableName: aws.String(plugin.config.Dynamodb),
	}
	resp, err := svc.Scan(params)
	if err != nil {
		return response, err
	}
	if resp.Count == aws.Int64(0) {
		response.Text = commandDetails.Texts["no_result"]
	} else {
		response.Text = commandDetails.Texts["response_text"]
		for _, item := range resp.Items {
			response.Text += fmt.Sprintf("\n * %s (%s)",
				aws.StringValue(item["name"].S),
				aws.StringValue(item["user"].S))
		}
	}

	return response, nil
}

// Functions to satisfy the interfaces are below

// Config returns the plugin configuration
func (plugin RememberPlugin) Config() IgorConfig {
	return plugin.config
}

type rememberConfig struct {
	languages      map[string]config.LanguagePluginDetails
	chosenLanguage string
	Dynamodb       string
	Admins         []string
	Blacklist      []string
}

func parseRememberConfig() (rememberConfig, error) {
	pluginConfig := struct {
		Remember rememberConfig
	}{}

	err := config.ParseConfig(&pluginConfig)
	if err != nil {
		return pluginConfig.Remember, err
	}

	return pluginConfig.Remember, nil
}

type rememberDetails struct {
	Dynamodb string
}

// Languages returns the languages available for the plugin
func (config rememberConfig) Languages() map[string]config.LanguagePluginDetails {
	return config.languages
}

// ChosenLanguage returns the language active for this plugin
func (config rememberConfig) ChosenLanguage() string {
	return config.chosenLanguage
}

// Description returns a global description of the plugin
func (plugin RememberPlugin) Description(language string) string {
	return getDescriptionText(plugin, language)
}

// Name returns the name of the plugin
func (plugin RememberPlugin) Name() string {
	return plugin.name
}

// Message returns a formatted version of the original message
func (plugin RememberPlugin) Message() string {
	return strings.ToLower(plugin.request.Text)
}
<commit_msg>Ensure the right type of error is thrown when no Dynamodb<commit_after>package plugins

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"

	"github.com/ArjenSchwarz/igor/config"
	"github.com/ArjenSchwarz/igor/slack"
)

// RememberPlugin provides remember functions
type RememberPlugin struct {
	name        string
	description string
	request     slack.Request
	config      rememberConfig
}

// Remember instantiates the RememberPlugin
func Remember(request slack.Request) (IgorPlugin, error) {
	pluginName := "remember"
	pluginConfig, err := parseRememberConfig()
	if err != nil {
		return RememberPlugin{}, err
	}
	pluginConfig.languages = getPluginLanguages(pluginName)
	plugin := RememberPlugin{
		name:    pluginName,
		request: request,
		config:  pluginConfig,
	}

	return plugin, nil
}

// Work parses the request and ensures a request comes through if any triggers
// are matched. Handled triggers:
//
//  * remember
//  * remember2
func (plugin RememberPlugin) Work() (slack.Response, error) {
	response := slack.Response{}
	if plugin.config.Dynamodb == "" {
		return response, CreateNoMatchError("No DynamoDB configured")
	}
	message, language := getCommandName(plugin)
	plugin.config.chosenLanguage = language
	switch message {
	case "remember":
		tmpresponse, err := plugin.handleRemember(response)
		if err != nil {
			return tmpresponse, err
		}
		response = tmpresponse
	case "show":
		return plugin.handleShow(response)
	case "forget":
		return plugin.handleForget(response)
	case "showall":
		return plugin.handleShowAll(response)
	}
	if response.Text == "" {
		return response, CreateNoMatchError("Nothing found")
	}
	return response, nil
}

// Describe provides the triggers RememberPlugin can handle
func (plugin RememberPlugin) Describe(language string) map[string]string {
	descriptions := make(map[string]string)
	if plugin.config.Dynamodb == "" {
		return descriptions
	}
	for commandName, values := range getAllCommands(plugin, language) {
		if commandName != "forget" || plugin.request.UserInList(plugin.config.Admins) {
			descriptions[values.Command] = values.Description
		}
	}
	return descriptions
}

func (plugin RememberPlugin) handleRemember(response slack.Response) (slack.Response, error) {
	commandDetails := getCommandDetails(plugin, "remember")
	if plugin.request.UserInList(plugin.config.Blacklist) {
		response.Text = commandDetails.Texts["forbidden"]
		return response, nil
	}
	parts := strings.Split(plugin.Message(), " ")
	name := strings.TrimSpace(parts[1])
	url := strings.TrimSpace(parts[2])

	response.Text = strings.Replace(commandDetails.Texts["response_text"], "[replace]", name, 1)
	sess, err := session.NewSession()
	if err != nil {
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.PutItemInput{
		Item: map[string]*dynamodb.AttributeValue{
			"name": {S: aws.String(name)},
			"url":  {S: aws.String(url)},
			"user": {S: aws.String(plugin.request.UserName)},
		},
		TableName: aws.String(plugin.config.Dynamodb),
	}
	_, err = svc.PutItem(params)

	return response, err
}

func (plugin RememberPlugin) handleForget(response slack.Response) (slack.Response, error) {
	commandDetails := getCommandDetails(plugin, "forget")
	if !plugin.request.UserInList(plugin.config.Admins) {
		response.Text = commandDetails.Texts["forbidden"]
		return response, nil
	}
	parts := strings.Split(plugin.Message(), " ")
	name := strings.TrimSpace(parts[1])

	response.Text = strings.Replace(commandDetails.Texts["response_text"], "[replace]", name, 1)
	sess, err := session.NewSession()
	if err != nil {
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.DeleteItemInput{
		Key: map[string]*dynamodb.AttributeValue{ // Required
			"name": {S: aws.String(name)},
		},
		TableName: aws.String(plugin.config.Dynamodb), // Required
	}
	_, err = svc.DeleteItem(params)
	return response, err
}

func (plugin RememberPlugin) handleShow(response slack.Response) (slack.Response, error) {
	var subject string
	commandDetails := getCommandDetails(plugin, "show")
	parts := strings.Split(plugin.Message(), " ")
	subject = strings.TrimSpace(strings.Replace(plugin.Message(), parts[0], "", 1))

	sess, err := session.NewSession()
	if err != nil {
		fmt.Println("failed to create session,", err)
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.GetItemInput{
		Key: map[string]*dynamodb.AttributeValue{
			"name": {S: aws.String(subject)},
		},
		TableName: aws.String(plugin.config.Dynamodb),
	}
	resp, err := svc.GetItem(params)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			if awsErr.Code() == "ResourceNotFoundException" {
				response.Text = commandDetails.Texts["no_result"]
				return response, nil
			}
		}
		return response, err
	}

	response.Text = aws.StringValue(resp.Item["name"].S)
	attach := slack.Attachment{
		ImageURL: aws.StringValue(resp.Item["url"].S),
	}
	response.AddAttachment(attach)
	response.SetPublic()
	return response, nil
}

func (plugin RememberPlugin) handleShowAll(response slack.Response) (slack.Response, error) {
	commandDetails := getCommandDetails(plugin, "showall")
	sess, err := session.NewSession()
	if err != nil {
		fmt.Println("failed to create session,", err)
		return response, err
	}

	svc := dynamodb.New(sess)

	params := &dynamodb.ScanInput{
		TableName: aws.String(plugin.config.Dynamodb),
	}
	resp, err := svc.Scan(params)
	if err != nil {
		return response, err
	}
	if resp.Count == aws.Int64(0) {
		response.Text = commandDetails.Texts["no_result"]
	} else {
		response.Text = commandDetails.Texts["response_text"]
		for _, item := range resp.Items {
			response.Text += fmt.Sprintf("\n * %s (%s)",
				aws.StringValue(item["name"].S),
				aws.StringValue(item["user"].S))
		}
	}

	return response, nil
}

// Functions to satisfy the interfaces are below

// Config returns the plugin configuration
func (plugin RememberPlugin) Config() IgorConfig {
	return plugin.config
}

type rememberConfig struct {
	languages      map[string]config.LanguagePluginDetails
	chosenLanguage string
	Dynamodb       string
	Admins         []string
	Blacklist      []string
}

func parseRememberConfig() (rememberConfig, error) {
	pluginConfig := struct {
		Remember rememberConfig
	}{}

	err := config.ParseConfig(&pluginConfig)
	if err != nil {
		return pluginConfig.Remember, err
	}

	return pluginConfig.Remember, nil
}

type rememberDetails struct {
	Dynamodb string
}

// Languages returns the languages available for the plugin
func (config rememberConfig) Languages() map[string]config.LanguagePluginDetails {
	return config.languages
}

// ChosenLanguage returns the language active for this plugin
func (config rememberConfig) ChosenLanguage() string {
	return config.chosenLanguage
}

// Description returns a global description of the plugin
func (plugin RememberPlugin) Description(language string) string {
	return getDescriptionText(plugin, language)
}

// Name returns the name of the plugin
func (plugin RememberPlugin) Name() string {
	return plugin.name
}

// Message returns a formatted version of the original message
func (plugin RememberPlugin) Message() string {
	return strings.ToLower(plugin.request.Text)
}
<|endoftext|>


<commit_before>// Copyright 2019 Google 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 generator

import (
	"context"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/sync/errgroup"
)

var goPkgOptRe = regexp.MustCompile(`(?m)^option go_package = (.*);`)

// denylist is a set of clients to NOT generate.
var denylist = map[string]bool{
	// TODO(codyoss): re-enable after issue is resolve -- https://github.com/googleapis/go-genproto/issues/357
	"google.golang.org/genproto/googleapis/cloud/recommendationengine/v1beta1": true,
}

// regenGenproto regenerates the genproto repository.
//
// regenGenproto recursively walks through each directory named by given
// arguments, looking for all .proto files. (Symlinks are not followed.) Any
// proto file without `go_package` option or whose option does not begin with
// the genproto prefix is ignored.
//
// If multiple roots contain files with the same name, eg "root1/path/to/file"
// and "root2/path/to/file", only the first file is processed; the rest are
// ignored.
//
// Protoc is executed on remaining files, one invocation per set of files
// declaring the same Go package.
func regenGenproto(ctx context.Context, genprotoDir, googleapisDir, protoDir string) error {
	log.Println("regenerating genproto")

	// The protoc include directory is actually the "src" directory of the repo.
	protoDir += "/src"

	// Create space to put generated .pb.go's.
	c := command("mkdir", "generated")
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	if err := c.Run(); err != nil {
		return err
	}

	// Record and map all .proto files to their Go packages.
	seenFiles := make(map[string]bool)
	pkgFiles := make(map[string][]string)
	for _, root := range []string{googleapisDir} {
		walkFn := func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.Mode().IsRegular() || !strings.HasSuffix(path, ".proto") {
				return nil
			}

			switch rel, err := filepath.Rel(root, path); {
			case err != nil:
				return err
			case seenFiles[rel]:
				return nil
			default:
				seenFiles[rel] = true
			}

			pkg, err := goPkg(path)
			if err != nil {
				return err
			}
			pkgFiles[pkg] = append(pkgFiles[pkg], path)
			return nil
		}
		if err := filepath.Walk(root, walkFn); err != nil {
			return err
		}
	}

	if len(pkgFiles) == 0 {
		return errors.New("couldn't find any pkgfiles")
	}

	// Run protoc on all protos of all packages.
	grp, _ := errgroup.WithContext(ctx)
	for pkg, fnames := range pkgFiles {
		if !strings.HasPrefix(pkg, "google.golang.org/genproto") || denylist[pkg] {
			continue
		}
		pk := pkg
		fn := fnames
		grp.Go(func() error {
			log.Println("running protoc on", pk)
			return protoc(genprotoDir, googleapisDir, protoDir, fn)
		})
	}
	if err := grp.Wait(); err != nil {
		return err
	}

	// Move all generated content to their correct locations in the repository,
	// because protoc puts it in a folder called generated/.

	// The period at the end is analagous to * (copy everything in this dir).
	c = command("cp", "-R", "generated/google.golang.org/genproto/.", ".")
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	if err := c.Run(); err != nil {
		return err
	}

	c = command("rm", "-rf", "generated")
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	if err := c.Run(); err != nil {
		return err
	}

	// Throw away changes to some special libs.
	for _, lib := range []string{"googleapis/grafeas/v1", "googleapis/devtools/containeranalysis/v1"} {
		c = command("git", "checkout", lib)
		c.Stdout = os.Stdout
		c.Stderr = os.Stderr
		c.Dir = genprotoDir
		if err := c.Run(); err != nil {
			return err
		}

		c = command("git", "clean", "-df", lib)
		c.Stdout = os.Stdout
		c.Stderr = os.Stderr
		c.Dir = genprotoDir
		if err := c.Run(); err != nil {
			return err
		}
	}

	// Clean up and check it all compiles.
	if err := vet(genprotoDir); err != nil {
		return err
	}

	if err := build(genprotoDir); err != nil {
		return err
	}

	return nil
}

// goPkg reports the import path declared in the given file's `go_package`
// option. If the option is missing, goPkg returns empty string.
func goPkg(fname string) (string, error) {
	content, err := ioutil.ReadFile(fname)
	if err != nil {
		return "", err
	}

	var pkgName string
	if match := goPkgOptRe.FindSubmatch(content); len(match) > 0 {
		pn, err := strconv.Unquote(string(match[1]))
		if err != nil {
			return "", err
		}
		pkgName = pn
	}
	if p := strings.IndexRune(pkgName, ';'); p > 0 {
		pkgName = pkgName[:p]
	}
	return pkgName, nil
}

// protoc executes the "protoc" command on files named in fnames, and outputs
// to "<genprotoDir>/generated".
func protoc(genprotoDir, googleapisDir, protoDir string, fnames []string) error {
	args := []string{"--experimental_allow_proto3_optional", fmt.Sprintf("--go_out=plugins=grpc:%s/generated", genprotoDir), "-I", googleapisDir, "-I", protoDir}
	args = append(args, fnames...)
	c := command("protoc", args...)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	return c.Run()
}
<commit_msg>chore(internal/gapicgen): stop frozen APIs from even generating (#2712)<commit_after>// Copyright 2019 Google 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 generator

import (
	"context"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/sync/errgroup"
)

var goPkgOptRe = regexp.MustCompile(`(?m)^option go_package = (.*);`)

// denylist is a set of clients to NOT generate.
var denylist = map[string]bool{
	// TODO(codyoss): re-enable after issue is resolve -- https://github.com/googleapis/go-genproto/issues/357
	"google.golang.org/genproto/googleapis/cloud/recommendationengine/v1beta1": true,

	// These two container APIs are currently frozen. They should not be updated
	// due to manual layer built on top of them.
	"google.golang.org/genproto/googleapis/grafeas/v1":                    true,
	"google.golang.org/genproto/googleapis/devtools/containeranalysis/v1": true,
}

// regenGenproto regenerates the genproto repository.
//
// regenGenproto recursively walks through each directory named by given
// arguments, looking for all .proto files. (Symlinks are not followed.) Any
// proto file without `go_package` option or whose option does not begin with
// the genproto prefix is ignored.
//
// If multiple roots contain files with the same name, eg "root1/path/to/file"
// and "root2/path/to/file", only the first file is processed; the rest are
// ignored.
//
// Protoc is executed on remaining files, one invocation per set of files
// declaring the same Go package.
func regenGenproto(ctx context.Context, genprotoDir, googleapisDir, protoDir string) error {
	log.Println("regenerating genproto")

	// The protoc include directory is actually the "src" directory of the repo.
	protoDir += "/src"

	// Create space to put generated .pb.go's.
	c := command("mkdir", "generated")
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	if err := c.Run(); err != nil {
		return err
	}

	// Record and map all .proto files to their Go packages.
	seenFiles := make(map[string]bool)
	pkgFiles := make(map[string][]string)
	for _, root := range []string{googleapisDir} {
		walkFn := func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if !info.Mode().IsRegular() || !strings.HasSuffix(path, ".proto") {
				return nil
			}

			switch rel, err := filepath.Rel(root, path); {
			case err != nil:
				return err
			case seenFiles[rel]:
				return nil
			default:
				seenFiles[rel] = true
			}

			pkg, err := goPkg(path)
			if err != nil {
				return err
			}
			pkgFiles[pkg] = append(pkgFiles[pkg], path)
			return nil
		}
		if err := filepath.Walk(root, walkFn); err != nil {
			return err
		}
	}

	if len(pkgFiles) == 0 {
		return errors.New("couldn't find any pkgfiles")
	}

	// Run protoc on all protos of all packages.
	grp, _ := errgroup.WithContext(ctx)
	for pkg, fnames := range pkgFiles {
		if !strings.HasPrefix(pkg, "google.golang.org/genproto") || denylist[pkg] {
			continue
		}
		pk := pkg
		fn := fnames
		grp.Go(func() error {
			log.Println("running protoc on", pk)
			return protoc(genprotoDir, googleapisDir, protoDir, fn)
		})
	}
	if err := grp.Wait(); err != nil {
		return err
	}

	// Move all generated content to their correct locations in the repository,
	// because protoc puts it in a folder called generated/.

	// The period at the end is analagous to * (copy everything in this dir).
	c = command("cp", "-R", "generated/google.golang.org/genproto/.", ".")
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	if err := c.Run(); err != nil {
		return err
	}

	c = command("rm", "-rf", "generated")
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	if err := c.Run(); err != nil {
		return err
	}

	// Clean up and check it all compiles.
	if err := vet(genprotoDir); err != nil {
		return err
	}

	if err := build(genprotoDir); err != nil {
		return err
	}

	return nil
}

// goPkg reports the import path declared in the given file's `go_package`
// option. If the option is missing, goPkg returns empty string.
func goPkg(fname string) (string, error) {
	content, err := ioutil.ReadFile(fname)
	if err != nil {
		return "", err
	}

	var pkgName string
	if match := goPkgOptRe.FindSubmatch(content); len(match) > 0 {
		pn, err := strconv.Unquote(string(match[1]))
		if err != nil {
			return "", err
		}
		pkgName = pn
	}
	if p := strings.IndexRune(pkgName, ';'); p > 0 {
		pkgName = pkgName[:p]
	}
	return pkgName, nil
}

// protoc executes the "protoc" command on files named in fnames, and outputs
// to "<genprotoDir>/generated".
func protoc(genprotoDir, googleapisDir, protoDir string, fnames []string) error {
	args := []string{"--experimental_allow_proto3_optional", fmt.Sprintf("--go_out=plugins=grpc:%s/generated", genprotoDir), "-I", googleapisDir, "-I", protoDir}
	args = append(args, fnames...)
	c := command("protoc", args...)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = genprotoDir
	return c.Run()
}
<|endoftext|>


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

//go:build ios
// +build ios

package mobile

// #cgo LDFLAGS: -framework CoreHaptics
//
// #import <CoreHaptics/CoreHaptics.h>
//
// static CHHapticEngine* engine;
//
// static void initializeVibrate(void) {
//   if (!CHHapticEngine.capabilitiesForHardware.supportsHaptics) {
//     return;
//   }
//
//   NSError* error = nil;
//   engine = [[CHHapticEngine alloc] initAndReturnError:&error];
//   if (error) {
//     return;
//   }
//
//   [engine startAndReturnError:&error];
//   if (error) {
//     return;
//   }
// }
//
// static void vibrate(double duration) {
//   if (!engine) {
//     return;
//   }
//
//   @autoreleasepool {
//     NSDictionary* hapticDict = @{
//       CHHapticPatternKeyPattern: @[
//         @{
//           CHHapticPatternKeyEvent: @{
//             CHHapticPatternKeyEventType:CHHapticEventTypeHapticContinuous,
//             CHHapticPatternKeyTime:@0.0,
//             CHHapticPatternKeyEventDuration:[NSNumber numberWithDouble:duration],
//             CHHapticPatternKeyEventParameters:@[
//               @{
//                 CHHapticPatternKeyParameterID: CHHapticEventParameterIDHapticIntensity,
//                 CHHapticPatternKeyParameterValue: @1.0,
//               },
//             ],
//           },
//         },
//       ],
//     };
//
//     NSError* error = nil;
//     CHHapticPattern* pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict
//                                                                      error:&error];
//     if (error) {
//       return;
//     }
//
//     id<CHHapticPatternPlayer> player = [engine createPlayerWithPattern:pattern
//                                                                  error:&error];
//     if (error) {
//       return;
//     }
//
//     [player startAtTime:0 error:&error];
//     if (error) {
//       NSLog(@"3, %@", [error localizedDescription]);
//       return;
//     }
//   }
// }
//
import "C"

import (
	"sync"
	"time"
)

func init() {
	C.initializeVibrate()
}

var vibrationM sync.Mutex

func (u *UserInterface) Vibrate(duration time.Duration) {
	vibrationM.Lock()
	defer vibrationM.Unlock()

	C.vibrate(C.double(float64(duration) / float64(time.Second)))
}
<commit_msg>internal/uidriver/mobile: Remove the warnings<commit_after>// Copyright 2021 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build ios
// +build ios

package mobile

// #cgo LDFLAGS: -framework CoreHaptics
//
// #import <CoreHaptics/CoreHaptics.h>
//
// static id initializeHapticEngine(void) {
//   if (@available(iOS 13.0, *)) {
//     if (!CHHapticEngine.capabilitiesForHardware.supportsHaptics) {
//       return nil;
//     }
//
//     NSError* error = nil;
//     CHHapticEngine* engine = [[CHHapticEngine alloc] initAndReturnError:&error];
//     if (error) {
//       return nil;
//     }
//
//     [engine startAndReturnError:&error];
//     if (error) {
//       return nil;
//     }
//     return engine;
//   }
//   return nil;
// }
//
// static void vibrate(double duration) {
//   if (@available(iOS 13.0, *)) {
//     static BOOL initializeHapticEngineCalled = NO;
//     static CHHapticEngine* engine = nil;
//     if (!initializeHapticEngineCalled) {
//       engine = (CHHapticEngine*)initializeHapticEngine();
//       initializeHapticEngineCalled = YES;
//     }
//     if (!engine) {
//       return;
//     }
//     @autoreleasepool {
//       NSDictionary* hapticDict = @{
//         (id<NSCopying>)(CHHapticPatternKeyPattern): @[
//           @{
//             (id<NSCopying>)(CHHapticPatternKeyEvent): @{
//               (id<NSCopying>)(CHHapticPatternKeyEventType):CHHapticEventTypeHapticContinuous,
//               (id<NSCopying>)(CHHapticPatternKeyTime):@0.0,
//               (id<NSCopying>)(CHHapticPatternKeyEventDuration):[NSNumber numberWithDouble:duration],
//               (id<NSCopying>)(CHHapticPatternKeyEventParameters):@[
//                 @{
//                   (id<NSCopying>)(CHHapticPatternKeyParameterID): CHHapticEventParameterIDHapticIntensity,
//                   (id<NSCopying>)(CHHapticPatternKeyParameterValue): @1.0,
//                 },
//               ],
//             },
//           },
//         ],
//       };
//
//       NSError* error = nil;
//       CHHapticPattern* pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict
//                                                                        error:&error];
//       if (error) {
//         return;
//       }
//
//       id<CHHapticPatternPlayer> player = [engine createPlayerWithPattern:pattern
//                                                                    error:&error];
//       if (error) {
//         return;
//       }
//
//       [player startAtTime:0 error:&error];
//       if (error) {
//         NSLog(@"3, %@", [error localizedDescription]);
//         return;
//       }
//     }
//   }
// }
//
import "C"

import (
	"sync"
	"time"
)

var vibrationM sync.Mutex

func (u *UserInterface) Vibrate(duration time.Duration) {
	vibrationM.Lock()
	defer vibrationM.Unlock()

	C.vibrate(C.double(float64(duration) / float64(time.Second)))
}
<|endoftext|>


<commit_before>package main

import (
	"blog4go"
	"fmt"
	//log "github.com/cihub/seelog"
	//log "github.com/Sirupsen/logrus"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

func main() {
	runtime.GOMAXPROCS(4)

	// blog
	writer, err := blog4go.NewFileLogWriter("output.log", true)
	if nil != err {
		fmt.Println(err.Error())
		os.Exit(1)
	}
	defer writer.Close()

	for i := 1; i < 10; i++ {
		//logging(writer)
		go logging(writer)
	}

	// seelog
	//logger, err := log.LoggerFromConfigAsFile("log_config.xml")
	//if nil != err {
	//fmt.Println(err.Error())
	//}

	//for i := 1; i < 10; i++ {
	//go logging1(logger)
	//}

	// logrus
	//file, err := os.OpenFile("output.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0644))
	//if nil != err {
	//fmt.Println(err.Error())
	//}
	//defer file.Close()
	//log.SetOutput(file)

	//for i := 1; i < 10; i++ {
	//go logging2()
	//}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, os.Interrupt, os.Kill)

	for {
		select {
		case <-c:
			fmt.Println("Exit..")
			time.Sleep(1 * time.Second)
			return
		}
	}
}

type T struct {
	A int
	B string
}

// blog
func logging(writer *blog4go.FileLogWriter) {
	t := T{123, "test"}
	d := int64(18)
	for {
		writer.Debug("test_debug")
		writer.Trace("test_trace")
		writer.Info("test_info")
		writer.Warn("test_warn")
		writer.Error("test_error")
		writer.Critical("test_critical")
		writer.Debugf("haha %s. en\\en, always %d and %5.4f, %t, %+v", "eddie", d, 3.14159, true, t)
		time.Sleep(2 * time.Second)
	}
}

// seelog
//func logging1(writer log.LoggerInterface) {
//for {
//writer.Debug("test")
//writer.Debugf("haha %s. en\\en, always %d and %.4f", "eddie", 18, 3.1415)
//}
//}

// logrus
//func logging2() {
//for {
//log.Print("test\n")
//log.Printf("%s [%s] haha %s. en\\en, always %d and %.4f\n", time.Now().Format("2006-01-02 15:04:05"), "DEBUG", "eddie", 18, 3.1415)
//}
//}
<commit_msg>bug fix<commit_after>package main

import (
	"blog4go"
	"fmt"
	//log "github.com/cihub/seelog"
	//log "github.com/Sirupsen/logrus"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

type MyHook struct {
	something string
}

func (self *MyHook) Fire(level blog4go.Level, message string) {
	if level >= blog4go.ERROR {
		fmt.Println(message)
	}
}

func main() {
	runtime.GOMAXPROCS(4)

	// blog
	writer, err := blog4go.NewFileLogWriter("output.log", true)
	if nil != err {
		fmt.Println(err.Error())
		os.Exit(1)
	}
	defer writer.Close()

	hook := new(MyHook)
	writer.SetHook(hook)

	for i := 1; i < 5; i++ {
		//logging(writer)
		go logging(writer)
	}

	// seelog
	//logger, err := log.LoggerFromConfigAsFile("log_config.xml")
	//if nil != err {
	//fmt.Println(err.Error())
	//}

	//for i := 1; i < 10; i++ {
	//go logging1(logger)
	//}

	// logrus
	//file, err := os.OpenFile("output.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0644))
	//if nil != err {
	//fmt.Println(err.Error())
	//}
	//defer file.Close()
	//log.SetOutput(file)

	//for i := 1; i < 10; i++ {
	//go logging2()
	//}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, os.Interrupt, os.Kill)

	for {
		select {
		case <-c:
			fmt.Println("Exit..")
			time.Sleep(1 * time.Second)
			return
		}
	}
}

type T struct {
	A int
	B string
}

// blog
func logging(writer *blog4go.FileLogWriter) {
	t := T{123, "test"}
	d := int64(18)
	for {
		writer.Debug("test_debug")
		writer.Trace("test_trace")
		writer.Info("test_info")
		writer.Warn("test_warn")
		writer.Error("test_error")
		writer.Critical("test_critical")
		writer.Criticalf("haha %s. en\\en, always %d and %5.4f, %t, %+v", "eddie", d, 3.14159, true, t)
		time.Sleep(5 * time.Second)
	}
}

// seelog
//func logging1(writer log.LoggerInterface) {
//for {
//writer.Debug("test")
//writer.Debugf("haha %s. en\\en, always %d and %.4f", "eddie", 18, 3.1415)
//}
//}

// logrus
//func logging2() {
//for {
//log.Print("test\n")
//log.Printf("%s [%s] haha %s. en\\en, always %d and %.4f\n", time.Now().Format("2006-01-02 15:04:05"), "DEBUG", "eddie", 18, 3.1415)
//}
//}
<|endoftext|>