<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"text/template"
	"time"
)

const (
	DEFAULT_EXCHANGE_TYPE      string = "direct"
	DEFAULT_QUEUE              string = "amqpc-queue"
	DEFAULT_ROUTING_KEY        string = "amqpc-key"
	DEFAULT_CONSUMER_TAG       string = "amqpc-consumer"
	DEFAULT_RELIABLE           bool   = true
	DEFAULT_CONCURRENCY        int    = 1
	DEFAULT_CONCURRENCY_PERIOD int    = 0
	DEFAULT_QUIET              bool   = false
)

// Flags
var (
	consumer = flag.Bool("c", true, "Act as a consumer")
	producer = flag.Bool("p", false, "Act as a producer")

	silent = flag.Bool("silent", false, "Turn off output")

	// RabbitMQ related
	uri          = flag.String("u", "amqp://guest:guest@localhost:5672/", "AMQP URI")
	exchange     = flag.String("e", "", "exchange on which to pub")
	exchangeType = flag.String("t", DEFAULT_EXCHANGE_TYPE, "Exchange type - direct|fanout|topic|x-custom")
	consumerTag  = flag.String("ct", DEFAULT_CONSUMER_TAG, "AMQP consumer tag (should not be blank)")
	reliable     = flag.Bool("r", DEFAULT_RELIABLE, "Wait for the publisher confirmation before exiting")

	// Test bench related
	concurrency       = flag.Int("g", DEFAULT_CONCURRENCY, "Concurrency")
	concurrencyPeriod = flag.Int("gp", DEFAULT_CONCURRENCY_PERIOD, "Concurrency period in ms (Producer only) - Interval at which spawn new Producer when concurrency is set")
	interval          = flag.Int("i", 0, "(Producer only) Interval at which send messages (in ms)")
	messageCount      = flag.Int("n", 0, "(Producer only) Number of messages to send")
)

func init() {
	flag.Usage = func() {
		readme := `
producer
--------
  amqpc [options] -p routingkey < file

  file is processed using text.template with one argument, the index of message
  index starts at 1

  eg: publish messages to default exchange ( '' ), routing key central.events

  echo 'message nº%s' | amqpc -c -n=1 somewhere

  see
  * http://golang.org/pkg/text/template/
  * https://golang.org/pkg/fmt/

`
		fmt.Fprintf(os.Stderr, readme, `{{ printf "%013d" . }}`)
		flag.PrintDefaults()
		os.Exit(1)
	}
	flag.Parse()
	if *silent {
		log.SetOutput(ioutil.Discard)
	}
}

func main() {
	done := make(chan error)

	args := flag.Args()

	if *producer {
		routingKey := args[0]
		bytes, _ := ioutil.ReadAll(os.Stdin)
		body := string(bytes[:])
		for i := 0; i < *concurrency; i++ {
			if *concurrencyPeriod > 0 {
				time.Sleep(time.Duration(*concurrencyPeriod) * time.Millisecond)
			}
			go startProducer(done, routingKey, body, *messageCount, *interval)
		}
	} else {
		queue := args[0]
		for i := 0; i < *concurrency; i++ {
			go startConsumer(done, queue)
		}
	}

	err := <-done
	if err != nil {
		log.Fatalf("Error : %s", err)
	}

	log.Printf("Exiting...")
}

func startConsumer(done chan error, queue string) {
	_, err := NewConsumer(
		*uri,
		queue,
		*consumerTag,
	)

	if err != nil {
		log.Fatalf("Error while starting consumer : %s", err)
	}

	<-done
}

func startProducer(done chan error, routingKey string, body string, messageCount, interval int) {
	var (
		p   *Producer = nil
		err error     = nil
	)

	if err != nil {
		log.Fatalf("Error while starting producer : %s", err)
	}

	for {
		p, err = NewProducer(
			*uri,
			*exchange,
			*exchangeType,
			routingKey,
			*consumerTag,
			true,
		)
		if err != nil {
			log.Printf("Error while starting producer : %s", err)
			time.Sleep(time.Second)
		} else {
			break
		}
	}

	i := 1
	duration := time.Duration(interval) * time.Millisecond
	template := template.Must(template.New("body").Parse(body))

	for {
		publish(p, routingKey, _body(template, i))

		i++
		if messageCount != 0 && i > messageCount {
			break
		}

		time.Sleep(duration)
	}

	done <- nil
}

func _body(template *template.Template, i int) string {
	var buffer bytes.Buffer
	if err := template.Execute(&buffer, i); err != nil {
		panic(err)
	}
	return buffer.String()
}

func publish(p *Producer, routingKey string, body string) {
	p.Publish(*exchange, routingKey, body)
}
<commit_msg>-s is an alias for --silent<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"text/template"
	"time"
)

const (
	DEFAULT_EXCHANGE_TYPE      string = "direct"
	DEFAULT_QUEUE              string = "amqpc-queue"
	DEFAULT_ROUTING_KEY        string = "amqpc-key"
	DEFAULT_CONSUMER_TAG       string = "amqpc-consumer"
	DEFAULT_RELIABLE           bool   = true
	DEFAULT_CONCURRENCY        int    = 1
	DEFAULT_CONCURRENCY_PERIOD int    = 0
	DEFAULT_QUIET              bool   = false
)

var silent bool

// Flags
var (
	consumer = flag.Bool("c", true, "Act as a consumer")
	producer = flag.Bool("p", false, "Act as a producer")

	// RabbitMQ related
	uri          = flag.String("u", "amqp://guest:guest@localhost:5672/", "AMQP URI")
	exchange     = flag.String("e", "", "exchange on which to pub")
	exchangeType = flag.String("t", DEFAULT_EXCHANGE_TYPE, "Exchange type - direct|fanout|topic|x-custom")
	consumerTag  = flag.String("ct", DEFAULT_CONSUMER_TAG, "AMQP consumer tag (should not be blank)")
	reliable     = flag.Bool("r", DEFAULT_RELIABLE, "Wait for the publisher confirmation before exiting")

	// Test bench related
	concurrency       = flag.Int("g", DEFAULT_CONCURRENCY, "Concurrency")
	concurrencyPeriod = flag.Int("gp", DEFAULT_CONCURRENCY_PERIOD, "Concurrency period in ms (Producer only) - Interval at which spawn new Producer when concurrency is set")
	interval          = flag.Int("i", 0, "(Producer only) Interval at which send messages (in ms)")
	messageCount      = flag.Int("n", 0, "(Producer only) Number of messages to send")
)

func init() {
	flag.BoolVar(&silent, "silent", false, "silent ( mute )")
	flag.BoolVar(&silent, "s", false, "shorthand for silent")

	flag.Usage = func() {
		readme := `
producer
--------
  amqpc [options] -p routingkey < file

  file is processed using text.template with one argument, the index of message
  index starts at 1

  eg: publish messages to default exchange ( '' ), routing key central.events

  echo 'message nº%s' | amqpc -c -n=1 somewhere

  see
  * http://golang.org/pkg/text/template/
  * https://golang.org/pkg/fmt/

`
		fmt.Fprintf(os.Stderr, readme, `{{ printf "%013d" . }}`)
		flag.PrintDefaults()
		os.Exit(1)
	}
	flag.Parse()
	if silent {
		log.SetOutput(ioutil.Discard)
	}
}

func main() {
	done := make(chan error)

	args := flag.Args()

	if *producer {
		routingKey := args[0]
		bytes, _ := ioutil.ReadAll(os.Stdin)
		body := string(bytes[:])
		for i := 0; i < *concurrency; i++ {
			if *concurrencyPeriod > 0 {
				time.Sleep(time.Duration(*concurrencyPeriod) * time.Millisecond)
			}
			go startProducer(done, routingKey, body, *messageCount, *interval)
		}
	} else {
		queue := args[0]
		for i := 0; i < *concurrency; i++ {
			go startConsumer(done, queue)
		}
	}

	err := <-done
	if err != nil {
		log.Fatalf("Error : %s", err)
	}

	log.Printf("Exiting...")
}

func startConsumer(done chan error, queue string) {
	_, err := NewConsumer(
		*uri,
		queue,
		*consumerTag,
	)

	if err != nil {
		log.Fatalf("Error while starting consumer : %s", err)
	}

	<-done
}

func startProducer(done chan error, routingKey string, body string, messageCount, interval int) {
	var (
		p   *Producer = nil
		err error     = nil
	)

	if err != nil {
		log.Fatalf("Error while starting producer : %s", err)
	}

	for {
		p, err = NewProducer(
			*uri,
			*exchange,
			*exchangeType,
			routingKey,
			*consumerTag,
			true,
		)
		if err != nil {
			log.Printf("Error while starting producer : %s", err)
			time.Sleep(time.Second)
		} else {
			break
		}
	}

	i := 1
	duration := time.Duration(interval) * time.Millisecond
	template := template.Must(template.New("body").Parse(body))

	for {
		publish(p, routingKey, _body(template, i))

		i++
		if messageCount != 0 && i > messageCount {
			break
		}

		time.Sleep(duration)
	}

	done <- nil
}

func _body(template *template.Template, i int) string {
	var buffer bytes.Buffer
	if err := template.Execute(&buffer, i); err != nil {
		panic(err)
	}
	return buffer.String()
}

func publish(p *Producer, routingKey string, body string) {
	p.Publish(*exchange, routingKey, body)
}
<|endoftext|>


<commit_before>/*
   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

   This file is licensed under the Apache License, Version 2.0 (the "License").
   You may not use this file except in compliance with the License. A copy of
   the License is located at

    http://aws.amazon.com/apache2.0/

   This file 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 (
    "encoding/json"
    "io/ioutil"
    "strconv"
    "testing"

    "github.com/google/uuid"

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

// Config defines a set of configuration values
type Config struct {
    Queue    string `json:"Queue"`
    WaitTime int    `json:"WaitTime"`
}

// configFile defines the name of the file containing configuration values
var configFileName = "config.json"

// globalConfig contains the configuration values
var globalConfig Config

func populateConfiguration(t *testing.T) error {
    // Get configuration from config.json

    // Get entire file as a JSON string
    content, err := ioutil.ReadFile(configFileName)
    if err != nil {
        return err
    }

    // Convert []byte to string
    text := string(content)

    // Marshall JSON string in text into global struct
    err = json.Unmarshal([]byte(text), &globalConfig)
    if err != nil {
        return err
    }

    t.Log("Queue:    " + globalConfig.Queue)
    t.Log("WaitTime: " + strconv.Itoa(globalConfig.WaitTime))

    return nil
}

func createLPQueue(sess *session.Session, queue *string, waitTime *int) (string, error) {
    // Create an SQS service client
    svc := sqs.New(sess)

    // snippet-start:[sqs.go.create_lp_queue.call]
    result, err := svc.CreateQueue(&sqs.CreateQueueInput{
        QueueName: queue,
        Attributes: aws.StringMap(map[string]string{
            "ReceiveMessageWaitTimeSeconds": strconv.Itoa(*waitTime),
        }),
    })
    if err != nil {
        return "", err
    }

    return *result.QueueUrl, nil
}

func deleteQueue(sess *session.Session, queueURL *string) error {
    // Create an SQS service client
    svc := sqs.New(sess)

    _, err := svc.DeleteQueue(&sqs.DeleteQueueInput{
        QueueUrl: queueURL,
    })
    if err != nil {
        return err
    }

    return nil
}

func TestQueue(t *testing.T) {
    err := populateConfiguration(t)
    if err != nil {
        t.Fatal(err)
    }

    // Create a session using credentials from ~/.aws/credentials
    // and the Region from ~/.aws/config
    sess := session.Must(session.NewSessionWithOptions(session.Options{
        SharedConfigState: session.SharedConfigEnable,
    }))

    queueCreated := false
    queueURL := ""

    if globalConfig.Queue == "" {
        // Create a unique, random queue name
        id := uuid.New()
        globalConfig.Queue = "myqueue-" + id.String()

        queueURL, err = createLPQueue(sess, &globalConfig.Queue, &globalConfig.WaitTime)
        if err != nil {
            t.Fatal(err)
        }

        t.Log("Created queue " + globalConfig.Queue)
        queueCreated = true
    }

    err = SendMsg(sess, &queueURL)
    if err != nil {
        t.Fatal(err)
    }

    t.Log("Sent message to queue " + globalConfig.Queue)

    if queueCreated {
        err = deleteQueue(sess, &queueURL)
        if err != nil {
            t.Log("You'll have to delete queue " + globalConfig.Queue + " yourself")
            t.Fatal(err)
        }

        t.Log("Deleted queue " + globalConfig.Queue)
    }
}
<commit_msg>Removed snippet tag from test file<commit_after>/*
   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

   This file is licensed under the Apache License, Version 2.0 (the "License").
   You may not use this file except in compliance with the License. A copy of
   the License is located at

    http://aws.amazon.com/apache2.0/

   This file 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 (
    "encoding/json"
    "io/ioutil"
    "strconv"
    "testing"

    "github.com/google/uuid"

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

// Config defines a set of configuration values
type Config struct {
    Queue    string `json:"Queue"`
    WaitTime int    `json:"WaitTime"`
}

// configFile defines the name of the file containing configuration values
var configFileName = "config.json"

// globalConfig contains the configuration values
var globalConfig Config

func populateConfiguration(t *testing.T) error {
    // Get configuration from config.json

    // Get entire file as a JSON string
    content, err := ioutil.ReadFile(configFileName)
    if err != nil {
        return err
    }

    // Convert []byte to string
    text := string(content)

    // Marshall JSON string in text into global struct
    err = json.Unmarshal([]byte(text), &globalConfig)
    if err != nil {
        return err
    }

    t.Log("Queue:    " + globalConfig.Queue)
    t.Log("WaitTime: " + strconv.Itoa(globalConfig.WaitTime))

    return nil
}

func createLPQueue(sess *session.Session, queue *string, waitTime *int) (string, error) {
    // Create an SQS service client
    svc := sqs.New(sess)

    result, err := svc.CreateQueue(&sqs.CreateQueueInput{
        QueueName: queue,
        Attributes: aws.StringMap(map[string]string{
            "ReceiveMessageWaitTimeSeconds": strconv.Itoa(*waitTime),
        }),
    })
    if err != nil {
        return "", err
    }

    return *result.QueueUrl, nil
}

func deleteQueue(sess *session.Session, queueURL *string) error {
    // Create an SQS service client
    svc := sqs.New(sess)

    _, err := svc.DeleteQueue(&sqs.DeleteQueueInput{
        QueueUrl: queueURL,
    })
    if err != nil {
        return err
    }

    return nil
}

func TestQueue(t *testing.T) {
    err := populateConfiguration(t)
    if err != nil {
        t.Fatal(err)
    }

    // Create a session using credentials from ~/.aws/credentials
    // and the Region from ~/.aws/config
    sess := session.Must(session.NewSessionWithOptions(session.Options{
        SharedConfigState: session.SharedConfigEnable,
    }))

    queueCreated := false
    queueURL := ""

    if globalConfig.Queue == "" {
        // Create a unique, random queue name
        id := uuid.New()
        globalConfig.Queue = "myqueue-" + id.String()

        queueURL, err = createLPQueue(sess, &globalConfig.Queue, &globalConfig.WaitTime)
        if err != nil {
            t.Fatal(err)
        }

        t.Log("Created queue " + globalConfig.Queue)
        queueCreated = true
    }

    err = SendMsg(sess, &queueURL)
    if err != nil {
        t.Fatal(err)
    }

    t.Log("Sent message to queue " + globalConfig.Queue)

    if queueCreated {
        err = deleteQueue(sess, &queueURL)
        if err != nil {
            t.Log("You'll have to delete queue " + globalConfig.Queue + " yourself")
            t.Fatal(err)
        }

        t.Log("Deleted queue " + globalConfig.Queue)
    }
}
<|endoftext|>


<commit_before>package emailmodels

import (
	"bytes"
	"fmt"
	"koding/db/mongodb/modelhelper"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/email/templates"
	"text/template"
	"time"
)

const (
	TimeLayout   = "3:04 PM"
	MessageLimit = 3
)

// ChannelSummary used for storing channel purpose and messages
type ChannelSummary struct {
	// Stores channel id
	Id int64
	// Unread count stores unread message count in the idle time
	UnreadCount int
	// AwaySince returns the oldest message in notification queue
	AwaySince time.Time

	BodyContent
}

func NewChannelSummary(a *models.Account, ch *models.Channel, awaySince time.Time) (*ChannelSummary, error) {
	cms, err := fetchLastMessages(a, ch, awaySince)
	if err != nil {
		return nil, err
	}

	count, err := fetchChannelMessageCount(a, ch, awaySince)
	if err != nil {
		return nil, err
	}

	if count == 0 {
		return &ChannelSummary{}, nil
	}

	mss, err := buildMessageSummaries(cms)
	if err != nil {
		return nil, err
	}

	cs := &ChannelSummary{
		Id:          ch.Id,
		AwaySince:   awaySince,
		UnreadCount: count,
	}

	cs.MessageGroups = mss

	return cs, nil
}

func (cs *ChannelSummary) Render() (string, error) {
	body := ""
	for _, message := range cs.MessageGroups {
		content, err := message.Render()
		if err != nil {
			return "", err
		}
		body += content
	}

	ct := template.Must(template.New("channel").Parse(templates.Channel))

	cs.Summary = body
	cs.Title = getTitle(cs.UnreadCount)

	buf := bytes.NewBuffer([]byte{})
	if err := ct.ExecuteTemplate(buf, "channel", cs); err != nil {
		return "", err
	}

	return buf.String(), nil
}

func getTitle(messageCount int) string {
	messagePlural := ""
	if messageCount > 1 {
		messagePlural = "s"
	}

	return fmt.Sprintf("You have %d new message%s:", messageCount, messagePlural)
}

func fetchLastMessages(a *models.Account, ch *models.Channel, awaySince time.Time) ([]models.ChannelMessage, error) {
	q := request.NewQuery()
	q.From = awaySince
	q.ExcludeField("AccountId", a.Id)
	cm := models.NewChannelMessage()

	return cm.FetchMessagesByChannelId(ch.Id, q)
}

func fetchChannelMessageCount(a *models.Account, ch *models.Channel, awaySince time.Time) (int, error) {
	q := request.NewQuery()
	q.From = awaySince
	q.ExcludeField("AccountId", a.Id)
	cm := models.NewChannelMessage()

	return cm.FetchTotalMessageCount(q)
}

func buildMessageSummaries(messages []models.ChannelMessage) ([]*MessageGroupSummary, error) {
	mss := make([]*MessageGroupSummary, 0)
	currentGroup := NewMessageGroupSummary()
	if len(messages) == 0 {
		return mss, nil
	}

	for _, message := range messages {
		// create new message summary
		ms := new(MessageSummary)
		ms.Body = message.Body
		ms.Time = message.CreatedAt.Format(TimeLayout)

		// if message has the same creator with the previous one
		if message.AccountId == currentGroup.AccountId {
			currentGroup.AddMessage(ms)
			continue
		}
		mg := NewMessageGroupSummary()
		// if current group has valid data
		if currentGroup.AccountId != 0 {
			*mg = *currentGroup
			mss = append(mss, mg)
		}

		currentGroup = NewMessageGroupSummary()
		a, err := models.FetchAccountById(message.AccountId)
		if err != nil {
			return mss, err
		}
		currentGroup.Nickname = a.Nick
		ma, err := modelhelper.GetAccountById(a.OldId)
		if err != nil {
			return mss, err
		}
		currentGroup.Hash = ma.Profile.Hash
		currentGroup.AccountId = message.AccountId
		currentGroup.AddMessage(ms)
	}

	if len(mss) == 0 || currentGroup.AccountId != mss[len(mss)-1].AccountId {
		mss = append(mss, currentGroup)
	}

	return mss, nil
}
<commit_msg>email: add comment lines to buildMessageSummaries<commit_after>package emailmodels

import (
	"bytes"
	"fmt"
	"koding/db/mongodb/modelhelper"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/email/templates"
	"text/template"
	"time"
)

const (
	TimeLayout   = "3:04 PM"
	MessageLimit = 3
)

// ChannelSummary used for storing channel purpose and messages
type ChannelSummary struct {
	// Stores channel id
	Id int64
	// Unread count stores unread message count in the idle time
	UnreadCount int
	// AwaySince returns the oldest message in notification queue
	AwaySince time.Time

	BodyContent
}

func NewChannelSummary(a *models.Account, ch *models.Channel, awaySince time.Time) (*ChannelSummary, error) {
	cms, err := fetchLastMessages(a, ch, awaySince)
	if err != nil {
		return nil, err
	}

	count, err := fetchChannelMessageCount(a, ch, awaySince)
	if err != nil {
		return nil, err
	}

	if count == 0 {
		return &ChannelSummary{}, nil
	}

	mss, err := buildMessageSummaries(cms)
	if err != nil {
		return nil, err
	}

	cs := &ChannelSummary{
		Id:          ch.Id,
		AwaySince:   awaySince,
		UnreadCount: count,
	}

	cs.MessageGroups = mss

	return cs, nil
}

func (cs *ChannelSummary) Render() (string, error) {
	body := ""
	for _, message := range cs.MessageGroups {
		content, err := message.Render()
		if err != nil {
			return "", err
		}
		body += content
	}

	ct := template.Must(template.New("channel").Parse(templates.Channel))

	cs.Summary = body
	cs.Title = getTitle(cs.UnreadCount)

	buf := bytes.NewBuffer([]byte{})
	if err := ct.ExecuteTemplate(buf, "channel", cs); err != nil {
		return "", err
	}

	return buf.String(), nil
}

func getTitle(messageCount int) string {
	messagePlural := ""
	if messageCount > 1 {
		messagePlural = "s"
	}

	return fmt.Sprintf("You have %d new message%s:", messageCount, messagePlural)
}

func fetchLastMessages(a *models.Account, ch *models.Channel, awaySince time.Time) ([]models.ChannelMessage, error) {
	q := request.NewQuery()
	q.From = awaySince
	q.ExcludeField("AccountId", a.Id)
	cm := models.NewChannelMessage()

	return cm.FetchMessagesByChannelId(ch.Id, q)
}

func fetchChannelMessageCount(a *models.Account, ch *models.Channel, awaySince time.Time) (int, error) {
	q := request.NewQuery()
	q.From = awaySince
	q.ExcludeField("AccountId", a.Id)
	cm := models.NewChannelMessage()

	return cm.FetchTotalMessageCount(q)
}

// buildMessageSummarries iterates over messages and decorates MessageGroupSummary
// It also groups messages, so if there are two consecutive messages belongs to the same user
// it is grouped under MessageGroupSummary.
func buildMessageSummaries(messages []models.ChannelMessage) ([]*MessageGroupSummary, error) {
	mss := make([]*MessageGroupSummary, 0)
	// each consequent user will have another MessageGroup
	currentGroup := NewMessageGroupSummary()
	if len(messages) == 0 {
		return mss, nil
	}

	for _, message := range messages {
		// create new message summary
		ms := new(MessageSummary)
		ms.Body = message.Body
		ms.Time = message.CreatedAt.Format(TimeLayout)

		// add message to message group since their sender accounts are same
		if message.AccountId == currentGroup.AccountId {
			currentGroup.AddMessage(ms)
			continue
		}
		// Different message sender so create a new group
		mg := NewMessageGroupSummary()
		// when currentGroup is not empty and add it to result array
		if currentGroup.AccountId != 0 {
			*mg = *currentGroup
			mss = append(mss, mg)
		}

		// and create a new group
		currentGroup = NewMessageGroupSummary()

		a, err := models.FetchAccountById(message.AccountId)
		if err != nil {
			return mss, err
		}
		currentGroup.Nickname = a.Nick
		ma, err := modelhelper.GetAccountById(a.OldId)
		if err != nil {
			return mss, err
		}
		currentGroup.Hash = ma.Profile.Hash
		currentGroup.AccountId = message.AccountId
		// push the latest message to the new message group
		currentGroup.AddMessage(ms)
	}

	// when last message has different owner append its message group to array
	if len(mss) == 0 || currentGroup.AccountId != mss[len(mss)-1].AccountId {
		mss = append(mss, currentGroup)
	}

	return mss, nil
}
<|endoftext|>


<commit_before>package pinnedpost

import (
	"socialapi/models"

	"github.com/koding/logging"
	"github.com/streadway/amqp"
)

type Controller struct{ log logging.Logger }

func (t *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	if delivery.Redelivered {
		t.log.Error("Redelivered message gave error again, putting to maintenance queue", err)
		delivery.Ack(false)
		return true
	}

	t.log.Error("an error occured putting message back to queue", err)
	delivery.Nack(false, true)
	return false
}

func New(log logging.Logger) *Controller {
	return &Controller{log: log}
}

// MessageReplyCreated handles the created replies
func (c *Controller) MessageReplyCreated(messageReply *models.MessageReply) error {
	parent, err := messageReply.FetchParent()
	if err != nil {
		return err
	}

	// only posts can be marked as pinned
	if parent.TypeConstant != models.ChannelMessage_TYPE_POST {
		return nil
	}

	reply, err := messageReply.FetchReply()
	if err != nil {
		return err
	}

	// add parent message to the author's pinned message list
	err = c.addMessage(parent.AccountId, parent.Id, parent.InitialChannelId)
	if err != nil && err != models.AlreadyInTheChannel {
		return err
	}

	// no need to try to add the same message again to the author's pinned
	// message list
	if parent.AccountId == reply.AccountId {
		return nil
	}

	// add parent message to the replier's pinned message list
	err = c.addMessage(reply.AccountId, parent.Id, parent.InitialChannelId)
	if err != nil && err != models.AlreadyInTheChannel {
		return err
	}

	return nil
}

func (c *Controller) addMessage(accountId, messageId, channelId int64) error {
	// fetch the parent channel for gorup name
	// get it from cache
	channel, err := models.ChannelById(channelId)
	if err != nil {
		return err
	}

	// get pinning channel for current user if it is created,, else create and get
	pinningChannel, err := models.EnsurePinnedActivityChannel(accountId, channel.GroupName)
	if err != nil {
		return err
	}

	// add parent message into pinning channel
	_, err = pinningChannel.AddMessage(messageId)
	// if message is already in the channel ignore the error, and mark process as successful
	if err == models.ErrAlreadyInTheChannel {
		return nil
	}

	return err
}
<commit_msg>pinnedpost: Error value is fixed<commit_after>package pinnedpost

import (
	"socialapi/models"

	"github.com/koding/logging"
	"github.com/streadway/amqp"
)

type Controller struct{ log logging.Logger }

func (t *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	if delivery.Redelivered {
		t.log.Error("Redelivered message gave error again, putting to maintenance queue", err)
		delivery.Ack(false)
		return true
	}

	t.log.Error("an error occured putting message back to queue", err)
	delivery.Nack(false, true)
	return false
}

func New(log logging.Logger) *Controller {
	return &Controller{log: log}
}

// MessageReplyCreated handles the created replies
func (c *Controller) MessageReplyCreated(messageReply *models.MessageReply) error {
	parent, err := messageReply.FetchParent()
	if err != nil {
		return err
	}

	// only posts can be marked as pinned
	if parent.TypeConstant != models.ChannelMessage_TYPE_POST {
		return nil
	}

	reply, err := messageReply.FetchReply()
	if err != nil {
		return err
	}

	// add parent message to the author's pinned message list
	err = c.addMessage(parent.AccountId, parent.Id, parent.InitialChannelId)
	if err != nil && err != models.AlreadyInTheChannel {
		return err
	}

	// no need to try to add the same message again to the author's pinned
	// message list
	if parent.AccountId == reply.AccountId {
		return nil
	}

	// add parent message to the replier's pinned message list
	err = c.addMessage(reply.AccountId, parent.Id, parent.InitialChannelId)
	if err != nil && err != models.ErrAlreadyInTheChannel {
		return err
	}

	return nil
}

func (c *Controller) addMessage(accountId, messageId, channelId int64) error {
	// fetch the parent channel for gorup name
	// get it from cache
	channel, err := models.ChannelById(channelId)
	if err != nil {
		return err
	}

	// get pinning channel for current user if it is created,, else create and get
	pinningChannel, err := models.EnsurePinnedActivityChannel(accountId, channel.GroupName)
	if err != nil {
		return err
	}

	// add parent message into pinning channel
	_, err = pinningChannel.AddMessage(messageId)
	// if message is already in the channel ignore the error, and mark process as successful
	if err == models.ErrAlreadyInTheChannel {
		return nil
	}

	return err
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"
	"io"
	"strings"
	"time"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/client"
	"github.com/docker/docker/api/client/inspect"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/pkg/ioutils"
	apiclient "github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types/swarm"
	"github.com/docker/go-units"
	"github.com/spf13/cobra"
)

type inspectOptions struct {
	refs   []string
	format string
	pretty bool
}

func newInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
	var opts inspectOptions

	cmd := &cobra.Command{
		Use:   "inspect [OPTIONS] SERVICE [SERVICE...]",
		Short: "Display detailed information on one or more services",
		Args:  cli.RequiresMinArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.refs = args

			if opts.pretty && len(opts.format) > 0 {
				return fmt.Errorf("--format is incompatible with human friendly format")
			}
			return runInspect(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
	flags.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format.")
	return cmd
}

func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	getRef := func(ref string) (interface{}, []byte, error) {
		service, _, err := client.ServiceInspectWithRaw(ctx, ref)
		if err == nil || !apiclient.IsErrServiceNotFound(err) {
			return service, nil, err
		}
		return nil, nil, fmt.Errorf("Error: no such service: %s", ref)
	}

	if !opts.pretty {
		return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRef)
	}

	return printHumanFriendly(dockerCli.Out(), opts.refs, getRef)
}

func printHumanFriendly(out io.Writer, refs []string, getRef inspect.GetRefFunc) error {
	for idx, ref := range refs {
		obj, _, err := getRef(ref)
		if err != nil {
			return err
		}
		printService(out, obj.(swarm.Service))

		// TODO: better way to do this?
		// print extra space between objects, but not after the last one
		if idx+1 != len(refs) {
			fmt.Fprintf(out, "\n\n")
		}
	}
	return nil
}

// TODO: use a template
func printService(out io.Writer, service swarm.Service) {
	fmt.Fprintf(out, "ID:\t\t%s\n", service.ID)
	fmt.Fprintf(out, "Name:\t\t%s\n", service.Spec.Name)
	if service.Spec.Labels != nil {
		fmt.Fprintln(out, "Labels:")
		for k, v := range service.Spec.Labels {
			fmt.Fprintf(out, " - %s=%s\n", k, v)
		}
	}

	if service.Spec.Mode.Global != nil {
		fmt.Fprintln(out, "Mode:\t\tGlobal")
	} else {
		fmt.Fprintln(out, "Mode:\t\tReplicated")
		if service.Spec.Mode.Replicated.Replicas != nil {
			fmt.Fprintf(out, " Replicas:\t%d\n", *service.Spec.Mode.Replicated.Replicas)
		}
	}

	if service.UpdateStatus.State != "" {
		fmt.Fprintln(out, "Update status:")
		fmt.Fprintf(out, " State:\t\t%s\n", service.UpdateStatus.State)
		fmt.Fprintf(out, " Started:\t%s ago\n", strings.ToLower(units.HumanDuration(time.Since(service.UpdateStatus.StartedAt))))
		if service.UpdateStatus.State == swarm.UpdateStateCompleted {
			fmt.Fprintf(out, " Completed:\t%s ago\n", strings.ToLower(units.HumanDuration(time.Since(service.UpdateStatus.CompletedAt))))
		}
		fmt.Fprintf(out, " Message:\t%s\n", service.UpdateStatus.Message)
	}

	fmt.Fprintln(out, "Placement:")
	if service.Spec.TaskTemplate.Placement != nil && len(service.Spec.TaskTemplate.Placement.Constraints) > 0 {
		ioutils.FprintfIfNotEmpty(out, " Constraints\t: %s\n", strings.Join(service.Spec.TaskTemplate.Placement.Constraints, ", "))
	}
	fmt.Fprintf(out, "UpdateConfig:\n")
	fmt.Fprintf(out, " Parallelism:\t%d\n", service.Spec.UpdateConfig.Parallelism)
	if service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 {
		fmt.Fprintf(out, " Delay:\t\t%s\n", service.Spec.UpdateConfig.Delay)
	}
	fmt.Fprintf(out, " On failure:\t%s\n", service.Spec.UpdateConfig.FailureAction)
	fmt.Fprintf(out, "ContainerSpec:\n")
	printContainerSpec(out, service.Spec.TaskTemplate.ContainerSpec)

	resources := service.Spec.TaskTemplate.Resources
	if resources != nil {
		fmt.Fprintln(out, "Resources:")
		printResources := func(out io.Writer, requirement string, r *swarm.Resources) {
			if r == nil || (r.MemoryBytes == 0 && r.NanoCPUs == 0) {
				return
			}
			fmt.Fprintf(out, " %s:\n", requirement)
			if r.NanoCPUs != 0 {
				fmt.Fprintf(out, "  CPU:\t\t%g\n", float64(r.NanoCPUs)/1e9)
			}
			if r.MemoryBytes != 0 {
				fmt.Fprintf(out, "  Memory:\t%s\n", units.BytesSize(float64(r.MemoryBytes)))
			}
		}
		printResources(out, "Reservations", resources.Reservations)
		printResources(out, "Limits", resources.Limits)
	}
	if len(service.Spec.Networks) > 0 {
		fmt.Fprintf(out, "Networks:")
		for _, n := range service.Spec.Networks {
			fmt.Fprintf(out, " %s", n.Target)
		}
	}

	if len(service.Endpoint.Ports) > 0 {
		fmt.Fprintln(out, "Ports:")
		for _, port := range service.Endpoint.Ports {
			ioutils.FprintfIfNotEmpty(out, " Name = %s\n", port.Name)
			fmt.Fprintf(out, " Protocol = %s\n", port.Protocol)
			fmt.Fprintf(out, " TargetPort = %d\n", port.TargetPort)
			fmt.Fprintf(out, " PublishedPort = %d\n", port.PublishedPort)
		}
	}
}

func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) {
	fmt.Fprintf(out, " Image:\t\t%s\n", containerSpec.Image)
	if len(containerSpec.Args) > 0 {
		fmt.Fprintf(out, " Args:\t\t%s\n", strings.Join(containerSpec.Args, " "))
	}
	if len(containerSpec.Env) > 0 {
		fmt.Fprintf(out, " Env:\t\t%s\n", strings.Join(containerSpec.Env, " "))
	}
	ioutils.FprintfIfNotEmpty(out, " Dir\t\t%s\n", containerSpec.Dir)
	ioutils.FprintfIfNotEmpty(out, " User\t\t%s\n", containerSpec.User)
	if len(containerSpec.Mounts) > 0 {
		fmt.Fprintln(out, " Mounts:")
		for _, v := range containerSpec.Mounts {
			fmt.Fprintf(out, "  Target = %s\n", v.Target)
			fmt.Fprintf(out, "  Source = %s\n", v.Source)
			fmt.Fprintf(out, "  ReadOnly = %v\n", v.ReadOnly)
			fmt.Fprintf(out, "  Type = %v\n", v.Type)
		}
	}
}
<commit_msg>Fix missing newline in service inspect --pretty<commit_after>package service

import (
	"fmt"
	"io"
	"strings"
	"time"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/client"
	"github.com/docker/docker/api/client/inspect"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/pkg/ioutils"
	apiclient "github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types/swarm"
	"github.com/docker/go-units"
	"github.com/spf13/cobra"
)

type inspectOptions struct {
	refs   []string
	format string
	pretty bool
}

func newInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
	var opts inspectOptions

	cmd := &cobra.Command{
		Use:   "inspect [OPTIONS] SERVICE [SERVICE...]",
		Short: "Display detailed information on one or more services",
		Args:  cli.RequiresMinArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.refs = args

			if opts.pretty && len(opts.format) > 0 {
				return fmt.Errorf("--format is incompatible with human friendly format")
			}
			return runInspect(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
	flags.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format.")
	return cmd
}

func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	getRef := func(ref string) (interface{}, []byte, error) {
		service, _, err := client.ServiceInspectWithRaw(ctx, ref)
		if err == nil || !apiclient.IsErrServiceNotFound(err) {
			return service, nil, err
		}
		return nil, nil, fmt.Errorf("Error: no such service: %s", ref)
	}

	if !opts.pretty {
		return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRef)
	}

	return printHumanFriendly(dockerCli.Out(), opts.refs, getRef)
}

func printHumanFriendly(out io.Writer, refs []string, getRef inspect.GetRefFunc) error {
	for idx, ref := range refs {
		obj, _, err := getRef(ref)
		if err != nil {
			return err
		}
		printService(out, obj.(swarm.Service))

		// TODO: better way to do this?
		// print extra space between objects, but not after the last one
		if idx+1 != len(refs) {
			fmt.Fprintf(out, "\n\n")
		}
	}
	return nil
}

// TODO: use a template
func printService(out io.Writer, service swarm.Service) {
	fmt.Fprintf(out, "ID:\t\t%s\n", service.ID)
	fmt.Fprintf(out, "Name:\t\t%s\n", service.Spec.Name)
	if service.Spec.Labels != nil {
		fmt.Fprintln(out, "Labels:")
		for k, v := range service.Spec.Labels {
			fmt.Fprintf(out, " - %s=%s\n", k, v)
		}
	}

	if service.Spec.Mode.Global != nil {
		fmt.Fprintln(out, "Mode:\t\tGlobal")
	} else {
		fmt.Fprintln(out, "Mode:\t\tReplicated")
		if service.Spec.Mode.Replicated.Replicas != nil {
			fmt.Fprintf(out, " Replicas:\t%d\n", *service.Spec.Mode.Replicated.Replicas)
		}
	}

	if service.UpdateStatus.State != "" {
		fmt.Fprintln(out, "Update status:")
		fmt.Fprintf(out, " State:\t\t%s\n", service.UpdateStatus.State)
		fmt.Fprintf(out, " Started:\t%s ago\n", strings.ToLower(units.HumanDuration(time.Since(service.UpdateStatus.StartedAt))))
		if service.UpdateStatus.State == swarm.UpdateStateCompleted {
			fmt.Fprintf(out, " Completed:\t%s ago\n", strings.ToLower(units.HumanDuration(time.Since(service.UpdateStatus.CompletedAt))))
		}
		fmt.Fprintf(out, " Message:\t%s\n", service.UpdateStatus.Message)
	}

	fmt.Fprintln(out, "Placement:")
	if service.Spec.TaskTemplate.Placement != nil && len(service.Spec.TaskTemplate.Placement.Constraints) > 0 {
		ioutils.FprintfIfNotEmpty(out, " Constraints\t: %s\n", strings.Join(service.Spec.TaskTemplate.Placement.Constraints, ", "))
	}
	fmt.Fprintf(out, "UpdateConfig:\n")
	fmt.Fprintf(out, " Parallelism:\t%d\n", service.Spec.UpdateConfig.Parallelism)
	if service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 {
		fmt.Fprintf(out, " Delay:\t\t%s\n", service.Spec.UpdateConfig.Delay)
	}
	fmt.Fprintf(out, " On failure:\t%s\n", service.Spec.UpdateConfig.FailureAction)
	fmt.Fprintf(out, "ContainerSpec:\n")
	printContainerSpec(out, service.Spec.TaskTemplate.ContainerSpec)

	resources := service.Spec.TaskTemplate.Resources
	if resources != nil {
		fmt.Fprintln(out, "Resources:")
		printResources := func(out io.Writer, requirement string, r *swarm.Resources) {
			if r == nil || (r.MemoryBytes == 0 && r.NanoCPUs == 0) {
				return
			}
			fmt.Fprintf(out, " %s:\n", requirement)
			if r.NanoCPUs != 0 {
				fmt.Fprintf(out, "  CPU:\t\t%g\n", float64(r.NanoCPUs)/1e9)
			}
			if r.MemoryBytes != 0 {
				fmt.Fprintf(out, "  Memory:\t%s\n", units.BytesSize(float64(r.MemoryBytes)))
			}
		}
		printResources(out, "Reservations", resources.Reservations)
		printResources(out, "Limits", resources.Limits)
	}
	if len(service.Spec.Networks) > 0 {
		fmt.Fprintf(out, "Networks:")
		for _, n := range service.Spec.Networks {
			fmt.Fprintf(out, " %s", n.Target)
		}
		fmt.Fprintln(out, "")
	}

	if len(service.Endpoint.Ports) > 0 {
		fmt.Fprintln(out, "Ports:")
		for _, port := range service.Endpoint.Ports {
			ioutils.FprintfIfNotEmpty(out, " Name = %s\n", port.Name)
			fmt.Fprintf(out, " Protocol = %s\n", port.Protocol)
			fmt.Fprintf(out, " TargetPort = %d\n", port.TargetPort)
			fmt.Fprintf(out, " PublishedPort = %d\n", port.PublishedPort)
		}
	}
}

func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) {
	fmt.Fprintf(out, " Image:\t\t%s\n", containerSpec.Image)
	if len(containerSpec.Args) > 0 {
		fmt.Fprintf(out, " Args:\t\t%s\n", strings.Join(containerSpec.Args, " "))
	}
	if len(containerSpec.Env) > 0 {
		fmt.Fprintf(out, " Env:\t\t%s\n", strings.Join(containerSpec.Env, " "))
	}
	ioutils.FprintfIfNotEmpty(out, " Dir\t\t%s\n", containerSpec.Dir)
	ioutils.FprintfIfNotEmpty(out, " User\t\t%s\n", containerSpec.User)
	if len(containerSpec.Mounts) > 0 {
		fmt.Fprintln(out, " Mounts:")
		for _, v := range containerSpec.Mounts {
			fmt.Fprintf(out, "  Target = %s\n", v.Target)
			fmt.Fprintf(out, "  Source = %s\n", v.Source)
			fmt.Fprintf(out, "  ReadOnly = %v\n", v.ReadOnly)
			fmt.Fprintf(out, "  Type = %v\n", v.Type)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"time"
)

const apiEndpoint string = "https://api.api.ai/v1/%s?v=%s"
const apiVersion string = "20150910"

var apiAccessToken = os.Getenv("APIAI_ACCESS_TOKEN")

//APIAIRequest : Incoming request format from APIAI
type APIAIRequest struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Result    struct {
		Source           string            `json:"source"`
		ResolvedQuery    string            `json:"resolvedQuery"`
		Action           string            `json:"action"`
		ActionIncomplete bool              `json:"actionIncomplete"`
		Parameters       map[string]string `json:"parameters"`
		Contexts         []struct {
			Name       string `json:"name"`
			Parameters struct {
				Name string `json:"name"`
			} `json:"parameters"`
			Lifespan int `json:"lifespan"`
		} `json:"contexts"`
		Metadata struct {
			IntentID   string `json:"intentId"`
			IntentName string `json:"intentName"`
		} `json:"metadata"`
		Fulfillment struct {
			Speech      string `json:"speech"`
			DisplayText string `json:"displayText"`
			Source      string `json:"source"`
		} `json:"fulfillment"`
	} `json:"result"`
	Status struct {
		Code      int    `json:"code"`
		ErrorType string `json:"errorType"`
	} `json:"status"`
}

//APIAIMessage : Response Message Structure
type APIAIMessage struct {
	Speech      string `json:"speech"`
	DisplayText string `json:"displayText"`
	Source      string `json:"source"`
}

// Send request to API.AI
func SendTextToApiAi(text string) (APIAIRequest, error) {

	record := APIAIRequest{}
	myUrl := fmt.Sprintf(apiEndpoint, "query", apiVersion)
	myUrl = myUrl + "&query=" + url.QueryEscape(text) + "&lang=en" + "&sessionId=1234567890"

	fmt.Println(myUrl)

	// Build the request
	req, err := http.NewRequest("GET", myUrl, nil)
	if err != nil {
		log.Fatal("NewRequest: ", err)
		return record, err
	}
	// Replace authToken by your Client access token
	authValue := "Bearer " + apiAccessToken
	req.Header.Add("Authorization", authValue)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal("Do: ", err)
		return record, err
	}

	// Callers should defer the close of resp.Body when done reading from it
	defer resp.Body.Close()

	// Use json.Decode for reading streams of JSON data
	if err := json.NewDecoder(resp.Body).Decode(&record); err != nil {
		log.Println(err)
	}

	fmt.Println("Status = ", record.Status.Code)
	fmt.Println("ErrorType = ", record.Status.ErrorType)
	fmt.Println("Response = ", record.Result.Fulfillment.Speech)

	return record, nil
}

// API.AI -> Weather
func HandleRequestFromApiAi(w http.ResponseWriter, req *http.Request) {

	decoder := json.NewDecoder(req.Body)

	var t APIAIRequest
	err := decoder.Decode(&t)
	if err != nil {
		log.Print(err)
		http.Error(w, "Error in decoding the Request data", http.StatusInternalServerError)
	}

	if t.Result.Action == "weather" {

		city := t.Result.Parameters["location"]
		z := RequestWeather(city)
		if z == nil {
			fmt.Printf("Program Error")
			log.Printf("Program Error")
		} else {
			emoji := ResolveEmoji(z.Code)
			apiResponseText := "The weather in " + city + " is " + z.Text + " " + emoji + ". The temperature is " + z.Temp + "º" + z.Scale + " and " + z.Humidity + "% humidity."
			msg := APIAIMessage{Source: "Weather Agent System", Speech: apiResponseText, DisplayText: apiResponseText}
			json.NewEncoder(w).Encode(msg)
		}

	}
}

// ResolveEmoji converts the weather code into an emoji
func ResolveEmoji(weatherCode string) (emoji string) {

	switch weatherCode {
	case "11", "12":
		return ":cloud_rain:"
	case "16":
		return ":snowflake:"
	case "20":
		return ":fog:"
	case "24":
		return ":dash:"
	case "25":
		return "cold"
	case "32":
		return "☀"
	case "36":
		return ":fire:"
	default:
		fmt.Printf("%s.", weatherCode)
		return ""
	}

}
<commit_msg>Amended emojis<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"time"
)

const apiEndpoint string = "https://api.api.ai/v1/%s?v=%s"
const apiVersion string = "20150910"

var apiAccessToken = os.Getenv("APIAI_ACCESS_TOKEN")

//APIAIRequest : Incoming request format from APIAI
type APIAIRequest struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Result    struct {
		Source           string            `json:"source"`
		ResolvedQuery    string            `json:"resolvedQuery"`
		Action           string            `json:"action"`
		ActionIncomplete bool              `json:"actionIncomplete"`
		Parameters       map[string]string `json:"parameters"`
		Contexts         []struct {
			Name       string `json:"name"`
			Parameters struct {
				Name string `json:"name"`
			} `json:"parameters"`
			Lifespan int `json:"lifespan"`
		} `json:"contexts"`
		Metadata struct {
			IntentID   string `json:"intentId"`
			IntentName string `json:"intentName"`
		} `json:"metadata"`
		Fulfillment struct {
			Speech      string `json:"speech"`
			DisplayText string `json:"displayText"`
			Source      string `json:"source"`
		} `json:"fulfillment"`
	} `json:"result"`
	Status struct {
		Code      int    `json:"code"`
		ErrorType string `json:"errorType"`
	} `json:"status"`
}

//APIAIMessage : Response Message Structure
type APIAIMessage struct {
	Speech      string `json:"speech"`
	DisplayText string `json:"displayText"`
	Source      string `json:"source"`
}

// Send request to API.AI
func SendTextToApiAi(text string) (APIAIRequest, error) {

	record := APIAIRequest{}
	myUrl := fmt.Sprintf(apiEndpoint, "query", apiVersion)
	myUrl = myUrl + "&query=" + url.QueryEscape(text) + "&lang=en" + "&sessionId=1234567890"

	fmt.Println(myUrl)

	// Build the request
	req, err := http.NewRequest("GET", myUrl, nil)
	if err != nil {
		log.Fatal("NewRequest: ", err)
		return record, err
	}
	// Replace authToken by your Client access token
	authValue := "Bearer " + apiAccessToken
	req.Header.Add("Authorization", authValue)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal("Do: ", err)
		return record, err
	}

	// Callers should defer the close of resp.Body when done reading from it
	defer resp.Body.Close()

	// Use json.Decode for reading streams of JSON data
	if err := json.NewDecoder(resp.Body).Decode(&record); err != nil {
		log.Println(err)
	}

	fmt.Println("Status = ", record.Status.Code)
	fmt.Println("ErrorType = ", record.Status.ErrorType)
	fmt.Println("Response = ", record.Result.Fulfillment.Speech)

	return record, nil
}

// API.AI -> Weather
func HandleRequestFromApiAi(w http.ResponseWriter, req *http.Request) {

	decoder := json.NewDecoder(req.Body)

	var t APIAIRequest
	err := decoder.Decode(&t)
	if err != nil {
		log.Print(err)
		http.Error(w, "Error in decoding the Request data", http.StatusInternalServerError)
	}

	if t.Result.Action == "weather" {

		city := t.Result.Parameters["location"]
		z := RequestWeather(city)
		if z == nil {
			fmt.Printf("Program Error")
			log.Printf("Program Error")
		} else {
			emoji := ResolveEmoji(z.Code)
			apiResponseText := "The weather in " + city + " is " + z.Text + " " + emoji + "! The temperature is " + z.Temp + "º" + z.Scale + " and " + z.Humidity + "% humidity."
			msg := APIAIMessage{Source: "Weather Agent System", Speech: apiResponseText, DisplayText: apiResponseText}
			json.NewEncoder(w).Encode(msg)
		}

	}
}

// ResolveEmoji converts the weather code into an emoji
func ResolveEmoji(weatherCode string) (emoji string) {

	switch weatherCode {
	case "11", "12":
		return "🌧☔"
	case "16":
		return "🌨❄"
	case "20":
		return "🌫"
	case "24":
		return "💨"
	case "25":
		return "🐧🐧"
	case "32":
		return "☀"
	case "36":
		return "🔥🔥"
	default:
		fmt.Printf("%s.", weatherCode)
		return ""
	}

}
<|endoftext|>


<commit_before>package rest_server

import (
    "fmt"
    "html"
    "log"
    "net/http"
    "encoding/json"

    //"gopkg.in/mgo.v2-unstable/bson"
    //"github.com/gorilla/mux"

)

func StartRestServer() {
    router := NewRouter()
    log.Fatal(http.ListenAndServe(":8080", router))
}

func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

func SetHttpError(w http.ResponseWriter, code int, msg string){
    jsonByte, _ := json.Marshal(map[string]string{
        "error": msg,
    })
    http.Error(
        w,
        string(jsonByte),
        code,
    )
}

/*
func EventsList(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    db, err_db := storage.GetDB()
    if err_db != nil {
        http.Error(w, err_db.Error(), http.StatusInternalServerError)
        return
    }
    var results []event_lib.BaseEventModel
    err_results := db.C("events").Find(bson.M{"ownerId": 0}).Sort("_id").All(&results)
    if err_results != nil {
        http.Error(w, err_results.Error(), http.StatusInternalServerError)
        return
    }
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(results)
}*/

<commit_msg>don't expose internal error messages to outsiders<commit_after>package rest_server

import (
    "fmt"
    "html"
    "log"
    "net/http"
    "encoding/json"

    //"gopkg.in/mgo.v2-unstable/bson"
    //"github.com/gorilla/mux"

)

func StartRestServer() {
    router := NewRouter()
    log.Fatal(http.ListenAndServe(":8080", router))
}

func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

func SetHttpError(w http.ResponseWriter, code int, msg string){
    if code == http.StatusInternalServerError {
        // log `msg` somewhere
        // don't expose internal error messages to outsiders
        msg = "Internal Server Error"
    }
    jsonByte, _ := json.Marshal(map[string]string{
        "error": msg,
    })
    http.Error(
        w,
        string(jsonByte),
        code,
    )
}

/*
func EventsList(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    db, err_db := storage.GetDB()
    if err_db != nil {
        http.Error(w, err_db.Error(), http.StatusInternalServerError)
        return
    }
    var results []event_lib.BaseEventModel
    err_results := db.C("events").Find(bson.M{"ownerId": 0}).Sort("_id").All(&results)
    if err_results != nil {
        http.Error(w, err_results.Error(), http.StatusInternalServerError)
        return
    }
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(results)
}*/

<|endoftext|>


<commit_before>package services_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/assets"
	. "github.com/cloudfoundry/cf-acceptance-tests/helpers/services"
)

var _ = Describe("Purging service offerings", func() {
	var broker ServiceBroker

	BeforeEach(func() {
		broker = NewServiceBroker(generator.RandomName(), assets.NewAssets().ServiceBroker, context)
		broker.Push()
		broker.Configure()
		broker.Create()
		broker.PublicizePlans()
	})

	AfterEach(func() {
		broker.Destroy()
	})

	It("removes all instances and plans of the service, then removes the service offering", func() {
		instanceName := "purge-offering-instance"

		marketplace := cf.Cf("marketplace").Wait(DEFAULT_TIMEOUT)
		Expect(marketplace).To(Exit(0))
		Expect(marketplace).To(Say(broker.Plans()[0].Name))

		broker.CreateServiceInstance(instanceName)

		services := cf.Cf("services").Wait(DEFAULT_TIMEOUT)
		Expect(marketplace).To(Exit(0))
		Expect(services).To(Say(instanceName))

		Expect(cf.Cf("delete", broker.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

		cf.AsUser(context.AdminUserContext(), DEFAULT_TIMEOUT, func() {
			Expect(cf.Cf("purge-service-offering", broker.Service.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		})

		services = cf.Cf("services").Wait(DEFAULT_TIMEOUT)
		Expect(services).To(Exit(0))
		Expect(services.Out.Contents()).NotTo(ContainSubstring(instanceName)) //TODO: Say?

		marketplace = cf.Cf("marketplace").Wait(DEFAULT_TIMEOUT)
		Expect(marketplace).To(Exit(0))
		Expect(marketplace.Out.Contents()).NotTo(ContainSubstring(broker.Service.Name)) //TODO: Say?
	})
})
<commit_msg>Refactor purge service offering test<commit_after>package services_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	"github.com/cloudfoundry/cf-acceptance-tests/helpers/assets"
	. "github.com/cloudfoundry/cf-acceptance-tests/helpers/services"
)

var _ = Describe("Purging service offerings", func() {
	var broker ServiceBroker

	BeforeEach(func() {
		broker = NewServiceBroker(generator.RandomName(), assets.NewAssets().ServiceBroker, context)
		broker.Push()
		broker.Configure()
		broker.Create()
		broker.PublicizePlans()
	})

	AfterEach(func() {
		broker.Destroy()
	})

	Context("when there are several existing service entities", func() {
		var appName, instanceName string

		BeforeEach(func() {
			appName = generator.RandomName()
			instanceName = generator.RandomName()

			createApp := cf.Cf("push", appName, "-p", assets.NewAssets().Dora).Wait(CF_PUSH_TIMEOUT)
			Expect(createApp).To(Exit(0), "failed creating app")

			broker.CreateServiceInstance(instanceName)

			services := cf.Cf("services").Wait(DEFAULT_TIMEOUT)
			Expect(services).To(Exit(0))
			Expect(services).To(Say(instanceName))

			bindService := cf.Cf("bind-service", appName, instanceName).Wait(DEFAULT_TIMEOUT)
			Expect(bindService).To(Exit(0), "failed binding app to service")
		})

		It("removes all instances and plans of the service, then removes the service offering", func() {
			marketplace := cf.Cf("marketplace").Wait(DEFAULT_TIMEOUT)
			Expect(marketplace).To(Exit(0))
			Expect(marketplace).To(Say(broker.Plans()[0].Name))

			Expect(cf.Cf("delete", broker.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))

			cf.AsUser(context.AdminUserContext(), DEFAULT_TIMEOUT, func() {
				Expect(cf.Cf("purge-service-offering", broker.Service.Name, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			})

			services := cf.Cf("services").Wait(DEFAULT_TIMEOUT)
			Expect(services).To(Exit(0))
			Expect(services).NotTo(Say(instanceName))
			Expect(services).NotTo(Say(appName))

			marketplace = cf.Cf("marketplace").Wait(DEFAULT_TIMEOUT)
			Expect(marketplace).To(Exit(0))
			Expect(marketplace).NotTo(Say(broker.Service.Name))
		})
	})
})
<|endoftext|>


<commit_before>package publisher

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"github.com/elastic/libbeat/outputs"
	"github.com/elastic/libbeat/outputs/elasticsearch"
	"github.com/elastic/libbeat/outputs/fileout"
	"github.com/elastic/libbeat/outputs/redis"
	"github.com/nranchev/go-libGeoIP"
)

// command line flags
var publishDisabled *bool

type PublisherType struct {
	name           string
	tags           []string
	disabled       bool
	Index          string
	Output         []outputs.OutputInterface
	TopologyOutput outputs.OutputInterface
	IgnoreOutgoing bool
	GeoLite        *libgeo.GeoIP

	RefreshTopologyTimer <-chan time.Time
	Queue                chan common.MapStr
}

type ShipperConfig struct {
	Name                  string
	Refresh_topology_freq int
	Ignore_outgoing       bool
	Topology_expire       int
	Tags                  []string
	Geoip                 common.Geoip
}

var Publisher PublisherType

type Topology struct {
	Name string `json:"name"`
	Ip   string `json:"ip"`
}

var EnabledOutputPlugins map[outputs.OutputPlugin]outputs.OutputInterface = map[outputs.OutputPlugin]outputs.OutputInterface{
	outputs.RedisOutput:         new(redis.RedisOutput),
	outputs.ElasticsearchOutput: new(elasticsearch.ElasticsearchOutput),
	outputs.FileOutput:          new(fileout.FileOutput),
}

func CmdLineFlags(flags *flag.FlagSet) {
	publishDisabled = flags.Bool("N", false, "Disable actual publishing for testing")
}

func PrintPublishEvent(event common.MapStr) {
	json, err := json.MarshalIndent(event, "", "  ")
	if err != nil {
		logp.Err("json.Marshal: %s", err)
	} else {
		logp.Debug("publish", "Publish: %s", string(json))
	}
}

func (publisher *PublisherType) GetServerName(ip string) string {
	// in case the IP is localhost, return current shipper name
	islocal, err := common.IsLoopback(ip)
	if err != nil {
		logp.Err("Parsing IP %s fails with: %s", ip, err)
		return ""
	} else {
		if islocal {
			return publisher.name
		}
	}
	// find the shipper with the desired IP
	if publisher.TopologyOutput != nil {
		return publisher.TopologyOutput.GetNameByIP(ip)
	} else {
		return ""
	}
}

func (publisher *PublisherType) publishFromQueue() {
	for mapstr := range publisher.Queue {
		err := publisher.publishEvent(mapstr)
		if err != nil {
			logp.Err("Publishing failed: %v", err)
		}
	}
}

func (publisher *PublisherType) publishEvent(event common.MapStr) error {

	// the timestamp is mandatory
	ts, ok := event["timestamp"].(common.Time)
	if !ok {
		return errors.New("Missing 'timestamp' field from event.")
	}

	// the count is mandatory
	err := event.EnsureCountField()
	if err != nil {
		return err
	}

	// the type is mandatory
	_, ok = event["type"].(string)
	if !ok {
		return errors.New("Missing 'type' field from event.")
	}

	var src_server, dst_server string
	src, ok := event["src"].(*common.Endpoint)
	if ok {
		src_server = publisher.GetServerName(src.Ip)
		event["client_ip"] = src.Ip
		event["client_port"] = src.Port
		event["client_proc"] = src.Proc
		event["client_server"] = src_server
		delete(event, "src")
	}
	dst, ok := event["dst"].(*common.Endpoint)
	if ok {
		dst_server = publisher.GetServerName(dst.Ip)
		event["ip"] = dst.Ip
		event["port"] = dst.Port
		event["proc"] = dst.Proc
		event["server"] = dst_server
		delete(event, "dst")
	}

	if publisher.IgnoreOutgoing && dst_server != "" &&
		dst_server != publisher.name {
		// duplicated transaction -> ignore it
		logp.Debug("publish", "Ignore duplicated transaction on %s: %s -> %s", publisher.name, src_server, dst_server)
		return nil
	}

	event["shipper"] = publisher.name
	if len(publisher.tags) > 0 {
		event["tags"] = publisher.tags
	}

	if publisher.GeoLite != nil {
		real_ip, exists := event["real_ip"]
		if exists && len(real_ip.(string)) > 0 {
			loc := publisher.GeoLite.GetLocationByIP(real_ip.(string))
			if loc != nil && loc.Latitude != 0 && loc.Longitude != 0 {
				event["client_location"] = fmt.Sprintf("%f, %f", loc.Latitude, loc.Longitude)
			}
		} else {
			if len(src_server) == 0 && src != nil { // only for external IP addresses
				loc := publisher.GeoLite.GetLocationByIP(src.Ip)
				if loc != nil && loc.Latitude != 0 && loc.Longitude != 0 {
					event["client_location"] = fmt.Sprintf("%f, %f", loc.Latitude, loc.Longitude)
				}
			}
		}
	}

	if logp.IsDebug("publish") {
		PrintPublishEvent(event)
	}

	// add transaction
	has_error := false
	if !publisher.disabled {
		for i := 0; i < len(publisher.Output); i++ {
			err := publisher.Output[i].PublishEvent(time.Time(ts), event)
			if err != nil {
				logp.Err("Fail to publish event type on output %s: %v", publisher.Output[i], err)
				has_error = true
			}
		}
	}

	if has_error {
		return errors.New("Fail to publish event")
	}
	return nil
}

func (publisher *PublisherType) UpdateTopologyPeriodically() {
	for _ = range publisher.RefreshTopologyTimer {
		publisher.PublishTopology()
	}
}

func (publisher *PublisherType) PublishTopology(params ...string) error {

	var localAddrs []string = params

	if len(params) == 0 {
		addrs, err := common.LocalIpAddrsAsStrings(false)
		if err != nil {
			logp.Err("Getting local IP addresses fails with: %s", err)
			return err
		}
		localAddrs = addrs
	}

	if publisher.TopologyOutput != nil {
		logp.Debug("publish", "Add topology entry for %s: %s", publisher.name, localAddrs)

		err := publisher.TopologyOutput.PublishIPs(publisher.name, localAddrs)
		if err != nil {
			return err
		}
	}

	return nil
}

func (publisher *PublisherType) Init(outputs map[string]outputs.MothershipConfig, shipper ShipperConfig) error {
	var err error
	publisher.IgnoreOutgoing = shipper.Ignore_outgoing

	publisher.disabled = *publishDisabled
	if publisher.disabled {
		logp.Info("Dry run mode. All output types except the file based one are disabled.")
	}

	publisher.GeoLite = common.LoadGeoIPData(shipper.Geoip)

	for outputId, plugin := range EnabledOutputPlugins {
		outputName := outputId.String()
		output, exists := outputs[outputName]
		if exists && output.Enabled && !publisher.disabled {
			err := plugin.Init(output, shipper.Topology_expire)
			if err != nil {
				logp.Err("Fail to initialize %s plugin as output: %s", outputName, err)
				return err
			}
			publisher.Output = append(publisher.Output, plugin)

			if output.Save_topology {
				if publisher.TopologyOutput != nil {
					logp.Err("Multiple outputs defined to store topology. Please add save_topology = true option only for one output.")
					return errors.New("Multiple outputs defined to store topology")
				}
				publisher.TopologyOutput = plugin
				logp.Info("Using %s to store the topology", outputName)
			}
		}
	}

	if !publisher.disabled {
		if len(publisher.Output) == 0 {
			logp.Info("No outputs are defined. Please define one under the shipper->output section.")
			return errors.New("No outputs are defined. Please define one under the shipper->output section.")
		}

		if publisher.TopologyOutput == nil {
			logp.Warn("No output is defined to store the topology. The server fields might not be filled.")
		}
	}

	publisher.name = shipper.Name
	if len(publisher.name) == 0 {
		// use the hostname
		publisher.name, err = os.Hostname()
		if err != nil {
			return err
		}

		logp.Info("No shipper name configured, using hostname '%s'", publisher.name)
	}

	publisher.tags = shipper.Tags

	if !publisher.disabled && publisher.TopologyOutput != nil {
		RefreshTopologyFreq := 10 * time.Second
		if shipper.Refresh_topology_freq != 0 {
			RefreshTopologyFreq = time.Duration(shipper.Refresh_topology_freq) * time.Second
		}
		publisher.RefreshTopologyTimer = time.Tick(RefreshTopologyFreq)
		logp.Info("Topology map refreshed every %s", RefreshTopologyFreq)

		// register shipper and its public IP addresses
		err = publisher.PublishTopology()
		if err != nil {
			logp.Err("Failed to publish topology: %s", err)
			return err
		}

		// update topology periodically
		go publisher.UpdateTopologyPeriodically()
	}

	publisher.Queue = make(chan common.MapStr, 1000)
	go publisher.publishFromQueue()

	return nil
}
<commit_msg>Fix error messages.<commit_after>package publisher

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"github.com/elastic/libbeat/outputs"
	"github.com/elastic/libbeat/outputs/elasticsearch"
	"github.com/elastic/libbeat/outputs/fileout"
	"github.com/elastic/libbeat/outputs/redis"
	"github.com/nranchev/go-libGeoIP"
)

// command line flags
var publishDisabled *bool

type PublisherType struct {
	name           string
	tags           []string
	disabled       bool
	Index          string
	Output         []outputs.OutputInterface
	TopologyOutput outputs.OutputInterface
	IgnoreOutgoing bool
	GeoLite        *libgeo.GeoIP

	RefreshTopologyTimer <-chan time.Time
	Queue                chan common.MapStr
}

type ShipperConfig struct {
	Name                  string
	Refresh_topology_freq int
	Ignore_outgoing       bool
	Topology_expire       int
	Tags                  []string
	Geoip                 common.Geoip
}

var Publisher PublisherType

type Topology struct {
	Name string `json:"name"`
	Ip   string `json:"ip"`
}

var EnabledOutputPlugins map[outputs.OutputPlugin]outputs.OutputInterface = map[outputs.OutputPlugin]outputs.OutputInterface{
	outputs.RedisOutput:         new(redis.RedisOutput),
	outputs.ElasticsearchOutput: new(elasticsearch.ElasticsearchOutput),
	outputs.FileOutput:          new(fileout.FileOutput),
}

func CmdLineFlags(flags *flag.FlagSet) {
	publishDisabled = flags.Bool("N", false, "Disable actual publishing for testing")
}

func PrintPublishEvent(event common.MapStr) {
	json, err := json.MarshalIndent(event, "", "  ")
	if err != nil {
		logp.Err("json.Marshal: %s", err)
	} else {
		logp.Debug("publish", "Publish: %s", string(json))
	}
}

func (publisher *PublisherType) GetServerName(ip string) string {
	// in case the IP is localhost, return current shipper name
	islocal, err := common.IsLoopback(ip)
	if err != nil {
		logp.Err("Parsing IP %s fails with: %s", ip, err)
		return ""
	} else {
		if islocal {
			return publisher.name
		}
	}
	// find the shipper with the desired IP
	if publisher.TopologyOutput != nil {
		return publisher.TopologyOutput.GetNameByIP(ip)
	} else {
		return ""
	}
}

func (publisher *PublisherType) publishFromQueue() {
	for mapstr := range publisher.Queue {
		err := publisher.publishEvent(mapstr)
		if err != nil {
			logp.Err("Publishing failed: %v", err)
		}
	}
}

func (publisher *PublisherType) publishEvent(event common.MapStr) error {

	// the timestamp is mandatory
	ts, ok := event["timestamp"].(common.Time)
	if !ok {
		return errors.New("Missing 'timestamp' field from event.")
	}

	// the count is mandatory
	err := event.EnsureCountField()
	if err != nil {
		return err
	}

	// the type is mandatory
	_, ok = event["type"].(string)
	if !ok {
		return errors.New("Missing 'type' field from event.")
	}

	var src_server, dst_server string
	src, ok := event["src"].(*common.Endpoint)
	if ok {
		src_server = publisher.GetServerName(src.Ip)
		event["client_ip"] = src.Ip
		event["client_port"] = src.Port
		event["client_proc"] = src.Proc
		event["client_server"] = src_server
		delete(event, "src")
	}
	dst, ok := event["dst"].(*common.Endpoint)
	if ok {
		dst_server = publisher.GetServerName(dst.Ip)
		event["ip"] = dst.Ip
		event["port"] = dst.Port
		event["proc"] = dst.Proc
		event["server"] = dst_server
		delete(event, "dst")
	}

	if publisher.IgnoreOutgoing && dst_server != "" &&
		dst_server != publisher.name {
		// duplicated transaction -> ignore it
		logp.Debug("publish", "Ignore duplicated transaction on %s: %s -> %s", publisher.name, src_server, dst_server)
		return nil
	}

	event["shipper"] = publisher.name
	if len(publisher.tags) > 0 {
		event["tags"] = publisher.tags
	}

	if publisher.GeoLite != nil {
		real_ip, exists := event["real_ip"]
		if exists && len(real_ip.(string)) > 0 {
			loc := publisher.GeoLite.GetLocationByIP(real_ip.(string))
			if loc != nil && loc.Latitude != 0 && loc.Longitude != 0 {
				event["client_location"] = fmt.Sprintf("%f, %f", loc.Latitude, loc.Longitude)
			}
		} else {
			if len(src_server) == 0 && src != nil { // only for external IP addresses
				loc := publisher.GeoLite.GetLocationByIP(src.Ip)
				if loc != nil && loc.Latitude != 0 && loc.Longitude != 0 {
					event["client_location"] = fmt.Sprintf("%f, %f", loc.Latitude, loc.Longitude)
				}
			}
		}
	}

	if logp.IsDebug("publish") {
		PrintPublishEvent(event)
	}

	// add transaction
	has_error := false
	if !publisher.disabled {
		for i := 0; i < len(publisher.Output); i++ {
			err := publisher.Output[i].PublishEvent(time.Time(ts), event)
			if err != nil {
				logp.Err("Fail to publish event type on output %s: %v", publisher.Output[i], err)
				has_error = true
			}
		}
	}

	if has_error {
		return errors.New("Fail to publish event")
	}
	return nil
}

func (publisher *PublisherType) UpdateTopologyPeriodically() {
	for _ = range publisher.RefreshTopologyTimer {
		publisher.PublishTopology()
	}
}

func (publisher *PublisherType) PublishTopology(params ...string) error {

	var localAddrs []string = params

	if len(params) == 0 {
		addrs, err := common.LocalIpAddrsAsStrings(false)
		if err != nil {
			logp.Err("Getting local IP addresses fails with: %s", err)
			return err
		}
		localAddrs = addrs
	}

	if publisher.TopologyOutput != nil {
		logp.Debug("publish", "Add topology entry for %s: %s", publisher.name, localAddrs)

		err := publisher.TopologyOutput.PublishIPs(publisher.name, localAddrs)
		if err != nil {
			return err
		}
	}

	return nil
}

func (publisher *PublisherType) Init(outputs map[string]outputs.MothershipConfig, shipper ShipperConfig) error {
	var err error
	publisher.IgnoreOutgoing = shipper.Ignore_outgoing

	publisher.disabled = *publishDisabled
	if publisher.disabled {
		logp.Info("Dry run mode. All output types except the file based one are disabled.")
	}

	publisher.GeoLite = common.LoadGeoIPData(shipper.Geoip)

	for outputId, plugin := range EnabledOutputPlugins {
		outputName := outputId.String()
		output, exists := outputs[outputName]
		if exists && output.Enabled && !publisher.disabled {
			err := plugin.Init(output, shipper.Topology_expire)
			if err != nil {
				logp.Err("Fail to initialize %s plugin as output: %s", outputName, err)
				return err
			}
			publisher.Output = append(publisher.Output, plugin)

			if output.Save_topology {
				if publisher.TopologyOutput != nil {
					logp.Err("Multiple outputs defined to store topology. Please add save_topology = true option only for one output.")
					return errors.New("Multiple outputs defined to store topology")
				}
				publisher.TopologyOutput = plugin
				logp.Info("Using %s to store the topology", outputName)
			}
		}
	}

	if !publisher.disabled {
		if len(publisher.Output) == 0 {
			logp.Info("No outputs are defined. Please define one under the output section.")
			return errors.New("No outputs are defined. Please define one under the output section.")
		}

		if publisher.TopologyOutput == nil {
			logp.Warn("No output is defined to store the topology. The server fields might not be filled.")
		}
	}

	publisher.name = shipper.Name
	if len(publisher.name) == 0 {
		// use the hostname
		publisher.name, err = os.Hostname()
		if err != nil {
			return err
		}

		logp.Info("No shipper name configured, using hostname '%s'", publisher.name)
	}

	publisher.tags = shipper.Tags

	if !publisher.disabled && publisher.TopologyOutput != nil {
		RefreshTopologyFreq := 10 * time.Second
		if shipper.Refresh_topology_freq != 0 {
			RefreshTopologyFreq = time.Duration(shipper.Refresh_topology_freq) * time.Second
		}
		publisher.RefreshTopologyTimer = time.Tick(RefreshTopologyFreq)
		logp.Info("Topology map refreshed every %s", RefreshTopologyFreq)

		// register shipper and its public IP addresses
		err = publisher.PublishTopology()
		if err != nil {
			logp.Err("Failed to publish topology: %s", err)
			return err
		}

		// update topology periodically
		go publisher.UpdateTopologyPeriodically()
	}

	publisher.Queue = make(chan common.MapStr, 1000)
	go publisher.publishFromQueue()

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 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 pubsub

import (
	"context"
	"fmt"
	"testing"
	"time"

	"cloud.google.com/go/internal/testutil"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	pubsubpb "google.golang.org/genproto/googleapis/pubsub/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func checkTopicListing(t *testing.T, c *Client, want []string) {
	topics, err := slurpTopics(c.Topics(context.Background()))
	if err != nil {
		t.Fatalf("error listing topics: %v", err)
	}
	var got []string
	for _, topic := range topics {
		got = append(got, topic.ID())
	}
	if !testutil.Equal(got, want) {
		t.Errorf("topic list: got: %v, want: %v", got, want)
	}
}

// All returns the remaining topics from this iterator.
func slurpTopics(it *TopicIterator) ([]*Topic, error) {
	var topics []*Topic
	for {
		switch topic, err := it.Next(); err {
		case nil:
			topics = append(topics, topic)
		case iterator.Done:
			return topics, nil
		default:
			return nil, err
		}
	}
}

func TestTopicID(t *testing.T) {
	const id = "id"
	c, srv := newFake(t)
	defer c.Close()
	defer srv.Close()

	s := c.Topic(id)
	if got, want := s.ID(), id; got != want {
		t.Errorf("Token.ID() = %q; want %q", got, want)
	}
}

func TestListTopics(t *testing.T) {
	c, srv := newFake(t)
	defer c.Close()
	defer srv.Close()

	var ids []string
	for i := 1; i <= 4; i++ {
		id := fmt.Sprintf("t%d", i)
		ids = append(ids, id)
		mustCreateTopic(t, c, id)
	}
	checkTopicListing(t, c, ids)
}

func TestListCompletelyEmptyTopics(t *testing.T) {
	c, srv := newFake(t)
	defer c.Close()
	defer srv.Close()

	checkTopicListing(t, c, nil)
}

func TestStopPublishOrder(t *testing.T) {
	// Check that Stop doesn't panic if called before Publish.
	// Also that Publish after Stop returns the right error.
	ctx := context.Background()
	c := &Client{projectID: "projid"}
	topic := c.Topic("t")
	topic.Stop()
	r := topic.Publish(ctx, &Message{})
	_, err := r.Get(ctx)
	if err != errTopicStopped {
		t.Errorf("got %v, want errTopicStopped", err)
	}
}

func TestPublishTimeout(t *testing.T) {
	ctx := context.Background()
	serv, err := testutil.NewServer()
	if err != nil {
		t.Fatal(err)
	}
	serv.Start()
	pubsubpb.RegisterPublisherServer(serv.Gsrv, &alwaysFailPublish{})
	conn, err := grpc.Dial(serv.Addr, grpc.WithInsecure())
	if err != nil {
		t.Fatal(err)
	}
	c, err := NewClient(ctx, "projectID", option.WithGRPCConn(conn))
	if err != nil {
		t.Fatal(err)
	}
	topic := c.Topic("t")
	topic.PublishSettings.Timeout = 3 * time.Second
	r := topic.Publish(ctx, &Message{})
	defer topic.Stop()
	select {
	case <-r.Ready():
		_, err = r.Get(ctx)
		if err != context.DeadlineExceeded {
			t.Fatalf("got %v, want context.DeadlineExceeded", err)
		}
	case <-time.After(2 * topic.PublishSettings.Timeout):
		t.Fatal("timed out")
	}
}

func TestUpdateTopic(t *testing.T) {
	ctx := context.Background()
	client, srv := newFake(t)
	defer client.Close()
	defer srv.Close()

	topic := mustCreateTopic(t, client, "T")
	config, err := topic.Config(ctx)
	if err != nil {
		t.Fatal(err)
	}
	want := TopicConfig{}
	if !testutil.Equal(config, want) {
		t.Errorf("got %+v, want %+v", config, want)
	}

	// replace labels
	labels := map[string]string{"label": "value"}
	config2, err := topic.Update(ctx, TopicConfigToUpdate{Labels: labels})
	if err != nil {
		t.Fatal(err)
	}
	want = TopicConfig{
		Labels:               labels,
		MessageStoragePolicy: MessageStoragePolicy{[]string{"US"}},
	}
	if !testutil.Equal(config2, want) {
		t.Errorf("got %+v, want %+v", config2, want)
	}

	// delete all labels
	labels = map[string]string{}
	config3, err := topic.Update(ctx, TopicConfigToUpdate{Labels: labels})
	if err != nil {
		t.Fatal(err)
	}
	want.Labels = nil
	if !testutil.Equal(config3, want) {
		t.Errorf("got %+v, want %+v", config3, want)
	}
}

type alwaysFailPublish struct {
	pubsubpb.PublisherServer
}

func (s *alwaysFailPublish) Publish(ctx context.Context, req *pubsubpb.PublishRequest) (*pubsubpb.PublishResponse, error) {
	return nil, status.Errorf(codes.Unavailable, "try again")
}

func mustCreateTopic(t *testing.T, c *Client, id string) *Topic {
	topic, err := c.CreateTopic(context.Background(), id)
	if err != nil {
		t.Fatal(err)
	}
	return topic
}
<commit_msg>pubsub: fix TestPublishTimeout<commit_after>// Copyright 2016 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 pubsub

import (
	"context"
	"fmt"
	"testing"
	"time"

	"cloud.google.com/go/internal/testutil"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	pubsubpb "google.golang.org/genproto/googleapis/pubsub/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func checkTopicListing(t *testing.T, c *Client, want []string) {
	topics, err := slurpTopics(c.Topics(context.Background()))
	if err != nil {
		t.Fatalf("error listing topics: %v", err)
	}
	var got []string
	for _, topic := range topics {
		got = append(got, topic.ID())
	}
	if !testutil.Equal(got, want) {
		t.Errorf("topic list: got: %v, want: %v", got, want)
	}
}

// All returns the remaining topics from this iterator.
func slurpTopics(it *TopicIterator) ([]*Topic, error) {
	var topics []*Topic
	for {
		switch topic, err := it.Next(); err {
		case nil:
			topics = append(topics, topic)
		case iterator.Done:
			return topics, nil
		default:
			return nil, err
		}
	}
}

func TestTopicID(t *testing.T) {
	const id = "id"
	c, srv := newFake(t)
	defer c.Close()
	defer srv.Close()

	s := c.Topic(id)
	if got, want := s.ID(), id; got != want {
		t.Errorf("Token.ID() = %q; want %q", got, want)
	}
}

func TestListTopics(t *testing.T) {
	c, srv := newFake(t)
	defer c.Close()
	defer srv.Close()

	var ids []string
	for i := 1; i <= 4; i++ {
		id := fmt.Sprintf("t%d", i)
		ids = append(ids, id)
		mustCreateTopic(t, c, id)
	}
	checkTopicListing(t, c, ids)
}

func TestListCompletelyEmptyTopics(t *testing.T) {
	c, srv := newFake(t)
	defer c.Close()
	defer srv.Close()

	checkTopicListing(t, c, nil)
}

func TestStopPublishOrder(t *testing.T) {
	// Check that Stop doesn't panic if called before Publish.
	// Also that Publish after Stop returns the right error.
	ctx := context.Background()
	c := &Client{projectID: "projid"}
	topic := c.Topic("t")
	topic.Stop()
	r := topic.Publish(ctx, &Message{})
	_, err := r.Get(ctx)
	if err != errTopicStopped {
		t.Errorf("got %v, want errTopicStopped", err)
	}
}

func TestPublishTimeout(t *testing.T) {
	ctx := context.Background()
	serv, err := testutil.NewServer()
	if err != nil {
		t.Fatal(err)
	}
	pubsubpb.RegisterPublisherServer(serv.Gsrv, &alwaysFailPublish{})
	serv.Start()
	conn, err := grpc.Dial(serv.Addr, grpc.WithInsecure())
	if err != nil {
		t.Fatal(err)
	}
	c, err := NewClient(ctx, "projectID", option.WithGRPCConn(conn))
	if err != nil {
		t.Fatal(err)
	}
	topic := c.Topic("t")
	topic.PublishSettings.Timeout = 3 * time.Second
	r := topic.Publish(ctx, &Message{})
	defer topic.Stop()
	select {
	case <-r.Ready():
		_, err = r.Get(ctx)
		if err != context.DeadlineExceeded {
			t.Fatalf("got %v, want context.DeadlineExceeded", err)
		}
	case <-time.After(2 * topic.PublishSettings.Timeout):
		t.Fatal("timed out")
	}
}

func TestUpdateTopic(t *testing.T) {
	ctx := context.Background()
	client, srv := newFake(t)
	defer client.Close()
	defer srv.Close()

	topic := mustCreateTopic(t, client, "T")
	config, err := topic.Config(ctx)
	if err != nil {
		t.Fatal(err)
	}
	want := TopicConfig{}
	if !testutil.Equal(config, want) {
		t.Errorf("got %+v, want %+v", config, want)
	}

	// replace labels
	labels := map[string]string{"label": "value"}
	config2, err := topic.Update(ctx, TopicConfigToUpdate{Labels: labels})
	if err != nil {
		t.Fatal(err)
	}
	want = TopicConfig{
		Labels:               labels,
		MessageStoragePolicy: MessageStoragePolicy{[]string{"US"}},
	}
	if !testutil.Equal(config2, want) {
		t.Errorf("got %+v, want %+v", config2, want)
	}

	// delete all labels
	labels = map[string]string{}
	config3, err := topic.Update(ctx, TopicConfigToUpdate{Labels: labels})
	if err != nil {
		t.Fatal(err)
	}
	want.Labels = nil
	if !testutil.Equal(config3, want) {
		t.Errorf("got %+v, want %+v", config3, want)
	}
}

type alwaysFailPublish struct {
	pubsubpb.PublisherServer
}

func (s *alwaysFailPublish) Publish(ctx context.Context, req *pubsubpb.PublishRequest) (*pubsubpb.PublishResponse, error) {
	return nil, status.Errorf(codes.Unavailable, "try again")
}

func mustCreateTopic(t *testing.T, c *Client, id string) *Topic {
	topic, err := c.CreateTopic(context.Background(), id)
	if err != nil {
		t.Fatal(err)
	}
	return topic
}
<|endoftext|>