<commit_before>// myLG is command line looking glass that written with Go language
// it tries from its own icmp and external looking glasses tools
package main

import (
	"errors"
	"fmt"
	"github.com/briandowns/spinner"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"

	"github.com/mehrdadrad/mylg/cli"
	"github.com/mehrdadrad/mylg/http/ping"
	"github.com/mehrdadrad/mylg/icmp"
	"github.com/mehrdadrad/mylg/lg"
	"github.com/mehrdadrad/mylg/ns"
	"github.com/mehrdadrad/mylg/peeringdb"
	"github.com/mehrdadrad/mylg/scan"
	"github.com/mehrdadrad/mylg/services/httpd"
	"github.com/mehrdadrad/mylg/whois"
)

// Provider represents looking glass
type Provider interface {
	Set(host, version string)
	GetDefaultNode() string
	GetNodes() []string
	ChangeNode(node string) bool
	Ping() (string, error)
	Trace() chan string
	BGP() chan string
}

const (
	version = "0.1.8"
)

var (
	// register looking glass hosts
	providers = map[string]Provider{"telia": new(lg.Telia), "level3": new(lg.Level3), "cogent": new(lg.Cogent)}
	pNames    = providerNames()
	req       = make(chan string, 1)
	nxt       = make(chan struct{}, 1)
	spin      = spinner.New(spinner.CharSets[26], 220*time.Millisecond)
	args      string
	prompt    string
	cPName    string
	nsr       *ns.Request
	c         *cli.Readline
)

// providerName
func providerNames() []string {
	pNames := []string{}
	for p := range providers {
		pNames = append(pNames, p)
	}
	return pNames
}

// validateProvider
func validateProvider(p string) (string, error) {
	pNames := []string{}
	match, _ := regexp.MatchString("("+strings.Join(pNames, "|")+")", p)
	p = strings.ToLower(p)
	if match {
		return p, nil
	}
	return "", errors.New("provider not support")

}
func init() {
	// initialize cli
	c = cli.Init("local", version)
	go c.Run(req, nxt)
	// initialize name server
	nsr = ns.NewRequest()
	go nsr.Init()
	// start web server
	go httpd.Run()
	// set default provider
	cPName = "local"
}

func main() {
	var (
		request string
		loop    = true
	)

	r, _ := regexp.Compile(`(ping|trace|bgp|lg|ns|dig|whois|peering|scan|hping|connect|node|local|mode|help|web|exit|quit)\s{0,1}(.*)`)

	for loop {
		select {
		case request, loop = <-req:
			if !loop {
				break
			}
			if len(request) < 1 {
				c.Next()
				continue
			}
			subReq := r.FindStringSubmatch(request)
			if len(subReq) == 0 {
				println("syntax error")
				c.Next()
				continue
			}
			prompt = c.GetPrompt()
			args = strings.TrimSpace(subReq[2])
			cmd := strings.TrimSpace(subReq[1])
			switch {
			case cmd == "hping" && cPName == "local":
				hping()
			case cmd == "ping" && cPName == "local":
				pingLocal()
			case cmd == "ping":
				pingLG()
			case cmd == "trace":
				trace()
			case cmd == "bgp":
				BGP()
			case cmd == "dig":
				nsr.Dig(args)
			case cmd == "node":
				node()
			case cmd == "local":
				nsr.Local()
				cPName = "local"
				c.SetPrompt(cPName)
			case cmd == "connect":
				connect()
			case cmd == "lg":
				c.SetPrompt("lg")
				c.UpdateCompleter("connect", pNames)
			case cmd == "ns":
				c.UpdateCompleter("connect", nsr.CountryList())
				c.UpdateCompleter("node", []string{})
				c.SetPrompt("ns")
			case cmd == "whois":
				whois.Lookup(args)
			case cmd == "peering":
				peeringdb.Search(args)
			case cmd == "scan":
				scanPorts()
			case cmd == "mode":
				mode()
			case cmd == "web":
				web()
			case cmd == "help":
				c.Help()
			case cmd == "exit", cmd == "quit":
				c.Close(nxt)
				close(req)
			}
			// next line
			c.Next()
		}
	}
}

// node handles node cmd
func node() {
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if _, ok := providers[cPName]; ok {
			if providers[cPName].ChangeNode(args) {
				c.UpdatePromptN(args, 3)
				return
			}
		}
		println("the specified node doesn't support")
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkNode(args) {
			println("error: argument is not valid")
		} else {
			c.UpdatePromptN(args, 3)
		}
	default:
		if cPName == "local" {
			println("local doesn't support node")
		}

	}
}

// web tries to open web interface at default web browser
func web() {
	var openCmd = "open"
	println("opening default web broswer ...")
	if runtime.GOOS != "darwin" {
		openCmd = "xdg-open"
	}
	cmd := exec.Command(openCmd, "http://localhost:8080")
	err := cmd.Start()
	if err != nil {
		println("error opening default browser")
	}

}

// connect handles connect cmd
func connect() {
	var (
		pName string
		err   error
	)
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if pName, err = validateProvider(args); err != nil {
			println("provider not available")
			c.Next()
			return
		}
		cPName = pName
		if _, ok := providers[cPName]; ok {
			c.UpdatePromptN(cPName+"/"+providers[cPName].GetDefaultNode(), 2)
			go func() {
				c.UpdateCompleter("node", providers[cPName].GetNodes())
			}()
		} else {
			println("it doesn't support")
		}
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkCountry(args) {
			println("error: argument is not valid")
		} else {
			c.SetPrompt("ns/" + args)
			c.UpdateCompleter("node", nsr.NodeList())
		}
	}
}

// mode set editor mode
func mode() {
	if args == "vim" {
		c.SetVim()
	} else if args == "emacs" {
		c.SetEmacs()
	} else {
		println("the request mode doesn't support")
	}
}

// trace tries to trace from local and lg
func trace() {
	switch {
	case strings.HasPrefix(prompt, "local"):
		trace := icmp.Trace{}
		trace.Run(args)
	case strings.HasPrefix(prompt, "lg"):
		providers[cPName].Set(args, "ipv4")
		for l := range providers[cPName].Trace() {
			println(l)
		}
	}
}

// hping tries to ping a web server by http
func hping() {
	p, err := ping.NewPing(args)
	if err != nil {
		println(err.Error())
	} else {
		p.Run()
	}
}

// pingLG tries to ping through a looking glass
func pingLG() {
	spin.Prefix = "please wait "
	spin.Start()
	providers[cPName].Set(args, "ipv4")
	m, err := providers[cPName].Ping()
	spin.Stop()
	if err != nil {
		println(err.Error())
	} else {
		println(m)
	}
}

// pingLocal tries to ping from local source ip
func pingLocal() {
	pFmt := "%d bytes from %s icmp_seq=%d time=%f ms"
	p, err := icmp.NewPing(args)
	if err != nil {
		return
	}
	resp := p.Run()
	for r := range resp {
		if r.Error != nil {
			println(r.Error.Error())
			continue
		}
		msg := fmt.Sprintf(pFmt, r.Size, r.Addr, r.Sequence, r.RTT)
		println(msg)
	}
}

// scanPorts tries to scan tcp/ip ports
func scanPorts() {
	scan, err := scan.NewScan(args)
	if err != nil {
		println(err.Error())
	} else {
		scan.Run()
	}
}

// BGP tries to get BGP lookup from a LG
func BGP() {
	if cPName == "local" {
		println("no provider selected")
		return
	}
	providers[cPName].Set(args, "ipv4")
	for l := range providers[cPName].BGP() {
		println(l)
	}
}
<commit_msg>bump version 0.1.9<commit_after>// myLG is command line looking glass that written with Go language
// it tries from its own icmp and external looking glasses tools
package main

import (
	"errors"
	"fmt"
	"github.com/briandowns/spinner"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"

	"github.com/mehrdadrad/mylg/cli"
	"github.com/mehrdadrad/mylg/http/ping"
	"github.com/mehrdadrad/mylg/icmp"
	"github.com/mehrdadrad/mylg/lg"
	"github.com/mehrdadrad/mylg/ns"
	"github.com/mehrdadrad/mylg/peeringdb"
	"github.com/mehrdadrad/mylg/scan"
	"github.com/mehrdadrad/mylg/services/httpd"
	"github.com/mehrdadrad/mylg/whois"
)

// Provider represents looking glass
type Provider interface {
	Set(host, version string)
	GetDefaultNode() string
	GetNodes() []string
	ChangeNode(node string) bool
	Ping() (string, error)
	Trace() chan string
	BGP() chan string
}

const (
	version = "0.1.9"
)

var (
	// register looking glass hosts
	providers = map[string]Provider{"telia": new(lg.Telia), "level3": new(lg.Level3), "cogent": new(lg.Cogent)}
	pNames    = providerNames()
	req       = make(chan string, 1)
	nxt       = make(chan struct{}, 1)
	spin      = spinner.New(spinner.CharSets[26], 220*time.Millisecond)
	args      string
	prompt    string
	cPName    string
	nsr       *ns.Request
	c         *cli.Readline
)

// providerName
func providerNames() []string {
	pNames := []string{}
	for p := range providers {
		pNames = append(pNames, p)
	}
	return pNames
}

// validateProvider
func validateProvider(p string) (string, error) {
	pNames := []string{}
	match, _ := regexp.MatchString("("+strings.Join(pNames, "|")+")", p)
	p = strings.ToLower(p)
	if match {
		return p, nil
	}
	return "", errors.New("provider not support")

}
func init() {
	// initialize cli
	c = cli.Init("local", version)
	go c.Run(req, nxt)
	// initialize name server
	nsr = ns.NewRequest()
	go nsr.Init()
	// start web server
	go httpd.Run()
	// set default provider
	cPName = "local"
}

func main() {
	var (
		request string
		loop    = true
	)

	r, _ := regexp.Compile(`(ping|trace|bgp|lg|ns|dig|whois|peering|scan|hping|connect|node|local|mode|help|web|exit|quit)\s{0,1}(.*)`)

	for loop {
		select {
		case request, loop = <-req:
			if !loop {
				break
			}
			if len(request) < 1 {
				c.Next()
				continue
			}
			subReq := r.FindStringSubmatch(request)
			if len(subReq) == 0 {
				println("syntax error")
				c.Next()
				continue
			}
			prompt = c.GetPrompt()
			args = strings.TrimSpace(subReq[2])
			cmd := strings.TrimSpace(subReq[1])
			switch {
			case cmd == "hping" && cPName == "local":
				hping()
			case cmd == "ping" && cPName == "local":
				pingLocal()
			case cmd == "ping":
				pingLG()
			case cmd == "trace":
				trace()
			case cmd == "bgp":
				BGP()
			case cmd == "dig":
				nsr.Dig(args)
			case cmd == "node":
				node()
			case cmd == "local":
				nsr.Local()
				cPName = "local"
				c.SetPrompt(cPName)
			case cmd == "connect":
				connect()
			case cmd == "lg":
				c.SetPrompt("lg")
				c.UpdateCompleter("connect", pNames)
			case cmd == "ns":
				c.UpdateCompleter("connect", nsr.CountryList())
				c.UpdateCompleter("node", []string{})
				c.SetPrompt("ns")
			case cmd == "whois":
				whois.Lookup(args)
			case cmd == "peering":
				peeringdb.Search(args)
			case cmd == "scan":
				scanPorts()
			case cmd == "mode":
				mode()
			case cmd == "web":
				web()
			case cmd == "help":
				c.Help()
			case cmd == "exit", cmd == "quit":
				c.Close(nxt)
				close(req)
			}
			// next line
			c.Next()
		}
	}
}

// node handles node cmd
func node() {
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if _, ok := providers[cPName]; ok {
			if providers[cPName].ChangeNode(args) {
				c.UpdatePromptN(args, 3)
				return
			}
		}
		println("the specified node doesn't support")
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkNode(args) {
			println("error: argument is not valid")
		} else {
			c.UpdatePromptN(args, 3)
		}
	default:
		if cPName == "local" {
			println("local doesn't support node")
		}

	}
}

// web tries to open web interface at default web browser
func web() {
	var openCmd = "open"
	println("opening default web broswer ...")
	if runtime.GOOS != "darwin" {
		openCmd = "xdg-open"
	}
	cmd := exec.Command(openCmd, "http://localhost:8080")
	err := cmd.Start()
	if err != nil {
		println("error opening default browser")
	}

}

// connect handles connect cmd
func connect() {
	var (
		pName string
		err   error
	)
	switch {
	case strings.HasPrefix(prompt, "lg"):
		if pName, err = validateProvider(args); err != nil {
			println("provider not available")
			c.Next()
			return
		}
		cPName = pName
		if _, ok := providers[cPName]; ok {
			c.UpdatePromptN(cPName+"/"+providers[cPName].GetDefaultNode(), 2)
			go func() {
				c.UpdateCompleter("node", providers[cPName].GetNodes())
			}()
		} else {
			println("it doesn't support")
		}
	case strings.HasPrefix(prompt, "ns"):
		if !nsr.ChkCountry(args) {
			println("error: argument is not valid")
		} else {
			c.SetPrompt("ns/" + args)
			c.UpdateCompleter("node", nsr.NodeList())
		}
	}
}

// mode set editor mode
func mode() {
	if args == "vim" {
		c.SetVim()
	} else if args == "emacs" {
		c.SetEmacs()
	} else {
		println("the request mode doesn't support")
	}
}

// trace tries to trace from local and lg
func trace() {
	switch {
	case strings.HasPrefix(prompt, "local"):
		trace := icmp.Trace{}
		trace.Run(args)
	case strings.HasPrefix(prompt, "lg"):
		providers[cPName].Set(args, "ipv4")
		for l := range providers[cPName].Trace() {
			println(l)
		}
	}
}

// hping tries to ping a web server by http
func hping() {
	p, err := ping.NewPing(args)
	if err != nil {
		println(err.Error())
	} else {
		p.Run()
	}
}

// pingLG tries to ping through a looking glass
func pingLG() {
	spin.Prefix = "please wait "
	spin.Start()
	providers[cPName].Set(args, "ipv4")
	m, err := providers[cPName].Ping()
	spin.Stop()
	if err != nil {
		println(err.Error())
	} else {
		println(m)
	}
}

// pingLocal tries to ping from local source ip
func pingLocal() {
	pFmt := "%d bytes from %s icmp_seq=%d time=%f ms"
	p, err := icmp.NewPing(args)
	if err != nil {
		return
	}
	resp := p.Run()
	for r := range resp {
		if r.Error != nil {
			println(r.Error.Error())
			continue
		}
		msg := fmt.Sprintf(pFmt, r.Size, r.Addr, r.Sequence, r.RTT)
		println(msg)
	}
}

// scanPorts tries to scan tcp/ip ports
func scanPorts() {
	scan, err := scan.NewScan(args)
	if err != nil {
		println(err.Error())
	} else {
		scan.Run()
	}
}

// BGP tries to get BGP lookup from a LG
func BGP() {
	if cPName == "local" {
		println("no provider selected")
		return
	}
	providers[cPName].Set(args, "ipv4")
	for l := range providers[cPName].BGP() {
		println(l)
	}
}
<|endoftext|>


<commit_before>package shaper_test

import (
	"fmt"
	"html"
)

import (
	"github.com/go-shaper/shaper"
)

////////////////////////////////////////////////////////////////////////////
// How to use it with the ready-made filters

func Example_output() {
	// == Using ready-made filters

	// Construct pipelines
	UpCase := shaper.NewFilter().ApplyToUpper()
	LCase := shaper.NewFilter().ApplyToLower()
	Replace := shaper.NewFilter().ApplyReplace("test", "biscuit", -1)

	// Test pipelines
	fmt.Printf("%s\n", UpCase.Process("This is a test."))
	fmt.Printf("%s\n", LCase.Process("This is a test."))
	fmt.Printf("%s\n", Replace.Process("This is a test."))

	// Demonstrating copy
	// to retain the `Replace` functionality but have another filter building
	// on top of it. Note: without the `Copy()`, the next call to Replace will
	// be affected by the ToUpper
	RU := Replace.Copy().ApplyToUpper()
	fmt.Printf("%s\n", RU.Process("This is a test."))

	// Note that we can reuse these stacks as many times as we like
	fmt.Printf("%s\n", Replace.Process("This is also a test. Testificate."))

	// We can also add stages later on - though we cannot remove stages using this style
	Replace.ApplyToUpper()
	fmt.Printf("%s\n", Replace.Process("This is also a test. Testificate."))
	LCase.ApplyReplace("test", "biscuit", -1)
	fmt.Printf("%s\n", LCase.Process("This is also a test. Testificate."))

	// Regexp.ReplaceAll
	RegReplace := shaper.NewFilter().ApplyRegexpReplaceAll("(?i)ht(ml)", "X$1")
	fmt.Printf("%s\n", RegReplace.Process("This is html Html HTML."))

	// Test trim
	spTrim := shaper.NewFilter().ApplyTrim()
	stFrom := " \t\n a   long \t lone\t gopher \n\t\r\n"
	stTo := spTrim.Process(stFrom)
	fmt.Printf("F: %q\nT: %q\n", stFrom, stTo)
	spTrim.ApplyRegSpaces()
	stTo = spTrim.Process(stFrom)
	fmt.Printf("R: %q\n", stTo)

	// Test ProcessAny
	fmt.Printf("%s\n", LCase.ProcessAny("This is also a test. Testificate."))
	fmt.Printf("%s\n",
		LCase.ProcessAny([]string{"This is also a test.", " Testificate."}))

	// == All done.
	fmt.Printf("Finished.\n")

	// Output:
	// THIS IS A TEST.
	// this is a test.
	// This is a biscuit.
	// THIS IS A BISCUIT.
	// This is also a biscuit. Testificate.
	// THIS IS ALSO A BISCUIT. TESTIFICATE.
	// this is also a biscuit. biscuitificate.
	// This is Xml Xml XML.
	// F: " \t\n a   long \t lone\t gopher \n\t\r\n"
	// T: "a   long \t lone\t gopher"
	// R: "a long lone gopher"
	// this is also a biscuit. biscuitificate.
	// this is also a biscuit. biscuitificate.
	// Finished.

}

////////////////////////////////////////////////////////////////////////////
// Extending shaper.Shaper

// Shaper extends shaper.Shaper
type Shaper struct {
	*shaper.Shaper
}

// NewFilter makes a new Shaper filter
func NewFilter() *Shaper {
	return &Shaper{Shaper: shaper.NewFilter()}
}

// ApplyHTMLUnescape will apply/add to html.UnescapeString filter to the Shaper
func (shpr *Shaper) ApplyHTMLUnescape() *Shaper {
	shpr.AddFilter(html.UnescapeString)
	return shpr
}

func ExampleShaper() {
	// == Extending shaper.Shaper to add your own filters
	var hu *Shaper
	hu = NewFilter()
	hu.ApplyHTMLUnescape()
	fmt.Printf("%s\n", hu.Process("2 >= 1"))
	// Output:
	// 2 >= 1
}
<commit_msg>- [+] add chaining exiting filters<commit_after>package shaper_test

import (
	"fmt"
	"html"
)

import (
	"github.com/go-shaper/shaper"
)

////////////////////////////////////////////////////////////////////////////
// How to use it with the ready-made filters

func Example_output() {
	// == Using ready-made filters

	// Construct pipelines
	UpCase := shaper.NewFilter().ApplyToUpper()
	LCase := shaper.NewFilter().ApplyToLower()
	Replace := shaper.NewFilter().ApplyReplace("test", "biscuit", -1)

	// Test pipelines
	fmt.Printf("%s\n", UpCase.Process("This is a test."))
	fmt.Printf("%s\n", LCase.Process("This is a test."))
	fmt.Printf("%s\n", Replace.Process("This is a test."))

	// Demonstrating copy
	// to retain the `Replace` functionality but have another filter building
	// on top of it. Note: without the `Copy()`, the next call to Replace will
	// be affected by the ToUpper
	RU := Replace.Copy().ApplyToUpper()
	fmt.Printf("%s\n", RU.Process("This is a test."))

	// Note that we can reuse these stacks as many times as we like
	fmt.Printf("%s\n", Replace.Process("This is also a test. Testificate."))

	// We can also add stages later on - though we cannot remove stages using this style
	Replace.ApplyToUpper()
	fmt.Printf("%s\n", Replace.Process("This is also a test. Testificate."))
	LCase.ApplyReplace("test", "biscuit", -1)
	fmt.Printf("%s\n", LCase.Process("This is also a test. Testificate."))

	// Regexp.ReplaceAll
	RegReplace := shaper.NewFilter().ApplyRegexpReplaceAll("(?i)ht(ml)", "X$1")
	fmt.Printf("%s\n", RegReplace.Process("This is html Html HTML."))

	// Test trim
	spTrim := shaper.NewFilter().ApplyTrim()
	stFrom := " \t\n a   long \t lone\t gopher \n\t\r\n"
	stTo := spTrim.Process(stFrom)
	fmt.Printf("F: %q\nT: %q\n", stFrom, stTo)
	spTrim.ApplyRegSpaces()
	stTo = spTrim.Process(stFrom)
	fmt.Printf("R: %q\n", stTo)

	// Test ProcessAny
	fmt.Printf("%s\n", LCase.ProcessAny("This is also a test. Testificate."))
	fmt.Printf("%s\n",
		LCase.ProcessAny([]string{"This is also a test.", " Testificate."}))

	// == All done.
	fmt.Printf("Finished.\n")

	// Output:
	// THIS IS A TEST.
	// this is a test.
	// This is a biscuit.
	// THIS IS A BISCUIT.
	// This is also a biscuit. Testificate.
	// THIS IS ALSO A BISCUIT. TESTIFICATE.
	// this is also a biscuit. biscuitificate.
	// This is Xml Xml XML.
	// F: " \t\n a   long \t lone\t gopher \n\t\r\n"
	// T: "a   long \t lone\t gopher"
	// R: "a long lone gopher"
	// this is also a biscuit. biscuitificate.
	// this is also a biscuit. biscuitificate.
	// Finished.

}

////////////////////////////////////////////////////////////////////////////
// Extending shaper.Shaper

// Shaper extends shaper.Shaper
type Shaper struct {
	*shaper.Shaper
}

// NewFilter makes a new Shaper filter
func NewFilter() *Shaper {
	return &Shaper{Shaper: shaper.NewFilter()}
}

// ApplyHTMLUnescape will apply/add to html.UnescapeString filter to the Shaper
func (shpr *Shaper) ApplyHTMLUnescape() *Shaper {
	shpr.AddFilter(html.UnescapeString)
	return shpr
}

func ExampleShaper() {
	// == Extending shaper.Shaper to add your own filters
	var hu *Shaper
	hu = NewFilter()
	hu.ApplyToUpper()
	fmt.Printf("%s\n", hu.Process("2 >= 1"))
	hu.ApplyHTMLUnescape()
	fmt.Printf("%s\n", hu.Process("2 >= 1"))
	// Output:
	// 2 >= 1
	// 2 >= 1
}
<|endoftext|>


<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2015 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*******************************************************************************/

package toybroker

import (
	"fmt"
	"net"
)

func MqttMainLoop(conn net.Conn, topics Topics, hook Hook) {
	connect, _, _, _, _, remaining, err := readMessage(conn)
	if connect != CONNECT || err != nil {
		conn.Write([]byte{CONNACK * 16, 2, 0, CONNACK_Rejected})
		return
	}
	clientID, _, _, loginName, loginPassword, err := unpackCONNECT(remaining)
	status, client := hook.Login(conn, clientID, loginName, loginPassword)
	if client == nil {
		conn.Write([]byte{CONNACK * 16, 2, 0, status})
		return
	}

	client.Send(packCONNACK(status))

	for {
		command, _, header_qos, retain, _, remaining, err := readMessage(conn)
		if err != nil {
			hook.Disconnect(clientID)
			break
		}
		switch command {
		case PUBLISH:
			topic, messageID, payload, err := unpackPUBLISH(remaining)
			debugOutput(fmt.Sprintf("PUBLISH:%s,%d,%v,%v", topic, messageID, payload, err))

			clientList, qosList := topics.List(topic)
			for i, clientID := range clientList {
				target := hook.GetClient(clientID)
				if qosList[i] > 0 && header_qos > 0 {
					qosList[i] = 1
				}
				target.Publish(false, qosList[i], false, topic, 0, payload)
			}
			if retain {
				topics.AddRetainMessage(topic, payload)
			}
		case PUBACK:
			debugOutput("PUBACK")
		case PUBREL:
			debugOutput("PUBREL")
		case SUBSCRIBE:
			messageID, subscribe_topics, err := unpackSUBSCRIBE(remaining)
			debugOutput(fmt.Sprintf("SUBSCRIBE:%v,%d,%v", subscribe_topics, messageID, err))
			qos := make([]byte, len(subscribe_topics))
			for i, topicName := range subscribe_topics {
				qos[i] = byte(hook.Subscribe(topics, topicName, clientID, 0))
			}
			client.Send(packSUBACK(messageID, qos))

			// Publish retain messages
			for i, topicName := range subscribe_topics {
				payload := topics.GetRetainMessage(topicName)
				debugOutput(fmt.Sprintf("GetRetainMessage(%s)=%v", topicName, payload))

				if len(payload) != 0 {
					debugOutput(fmt.Sprintf("SendRetainMessage:%s->%v", topicName, payload))
					client.Publish(false, int(qos[i]), true, topicName, 0, payload)
				}
			}

		case UNSUBSCRIBE:
			messageID, unsubscribe_topics, err := unpackUNSUBSCRIBE(remaining)
			debugOutput(fmt.Sprintf("UNSUBSCRIBE:%v,%d,%v", unsubscribe_topics, messageID, err))
			for _, topicName := range unsubscribe_topics {
				hook.Unsubscribe(topics, topicName, clientID)
			}
			client.Send(packUNSUBACK(messageID))
		case PINGREQ:
			debugOutput("PINGREQ")
			client.Send(packPINGRESP())
		case DISCONNECT:
			debugOutput("DISCONNECT")
			hook.Disconnect(clientID)
			break
		default:
			debugOutput("Invalid Command")
			hook.Disconnect(clientID)
			break
		}
	}
}
<commit_msg>add PUBACK<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2015 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*******************************************************************************/

package toybroker

import (
	"fmt"
	"net"
)

func MqttMainLoop(conn net.Conn, topics Topics, hook Hook) {
	connect, _, _, _, _, remaining, err := readMessage(conn)
	if connect != CONNECT || err != nil {
		conn.Write([]byte{CONNACK * 16, 2, 0, CONNACK_Rejected})
		return
	}
	clientID, _, _, loginName, loginPassword, err := unpackCONNECT(remaining)
	status, client := hook.Login(conn, clientID, loginName, loginPassword)
	if client == nil {
		conn.Write([]byte{CONNACK * 16, 2, 0, status})
		return
	}

	client.Send(packCONNACK(status))

	for {
		command, _, header_qos, retain, _, remaining, err := readMessage(conn)
		if err != nil {
			hook.Disconnect(clientID)
			break
		}
		switch command {
		case PUBLISH:
			topic, messageID, payload, err := unpackPUBLISH(remaining)
			debugOutput(fmt.Sprintf("PUBLISH:%s,%d,%v,%v", topic, messageID, payload, err))

			clientList, qosList := topics.List(topic)
			for i, clientID := range clientList {
				target := hook.GetClient(clientID)
				if qosList[i] > 0 && header_qos > 0 {
					qosList[i] = 1
				}
				target.Publish(false, qosList[i], false, topic, 0, payload)
			}
			if retain {
				topics.AddRetainMessage(topic, payload)
			}
			if header_qos == 1 {
				conn.Write([]byte{PUBACK * 16, 2, byte(messageID >> 8), byte(messageID & 0xFF)})
			}
		case PUBACK:
			debugOutput("PUBACK")
		case PUBREL:
			debugOutput("PUBREL")
		case SUBSCRIBE:
			messageID, subscribe_topics, err := unpackSUBSCRIBE(remaining)
			debugOutput(fmt.Sprintf("SUBSCRIBE:%v,%d,%v", subscribe_topics, messageID, err))
			qos := make([]byte, len(subscribe_topics))
			for i, topicName := range subscribe_topics {
				qos[i] = byte(hook.Subscribe(topics, topicName, clientID, 0))
			}
			client.Send(packSUBACK(messageID, qos))

			// Publish retain messages
			for i, topicName := range subscribe_topics {
				payload := topics.GetRetainMessage(topicName)
				debugOutput(fmt.Sprintf("GetRetainMessage(%s)=%v", topicName, payload))

				if len(payload) != 0 {
					debugOutput(fmt.Sprintf("SendRetainMessage:%s->%v", topicName, payload))
					client.Publish(false, int(qos[i]), true, topicName, 0, payload)
				}
			}

		case UNSUBSCRIBE:
			messageID, unsubscribe_topics, err := unpackUNSUBSCRIBE(remaining)
			debugOutput(fmt.Sprintf("UNSUBSCRIBE:%v,%d,%v", unsubscribe_topics, messageID, err))
			for _, topicName := range unsubscribe_topics {
				hook.Unsubscribe(topics, topicName, clientID)
			}
			client.Send(packUNSUBACK(messageID))
		case PINGREQ:
			debugOutput("PINGREQ")
			client.Send(packPINGRESP())
		case DISCONNECT:
			debugOutput("DISCONNECT")
			hook.Disconnect(clientID)
			break
		default:
			debugOutput("Invalid Command")
			hook.Disconnect(clientID)
			break
		}
	}
}
<|endoftext|>


<commit_before>/* This is a FLEXible file which can be used by both client and daemon.
 * Teehee.
 */
package shared

var Version = "0.25"
var UserAgent = "LXD " + Version

/*
 * Please increment the api compat number every time you change the API.
 *
 * Version 1.0: ping
 */
var APICompat = 1
var APIVersion = "1.0"
<commit_msg>Release LXD 0.26<commit_after>/* This is a FLEXible file which can be used by both client and daemon.
 * Teehee.
 */
package shared

var Version = "0.26"
var UserAgent = "LXD " + Version

/*
 * Please increment the api compat number every time you change the API.
 *
 * Version 1.0: ping
 */
var APICompat = 1
var APIVersion = "1.0"
<|endoftext|>


<commit_before>// The shellescape package provides the function Quote to escape arbitrary
// strings for a safe use as command line arguments in the most common
// POSIX shells.

package shellescape

import (
	"regexp"
	"strings"
)

var pattern *regexp.Regexp

func init() {
	pattern = regexp.MustCompilePOSIX("[a-zA-Z0-9_^@%+=:,./-]")
}

// Quote replaces all occurrences in the string s of the
// single quote character with an escaped version.
func Quote(s string) string {
	if len(s) == 0 {
		return "''"
	}
	if pattern.MatchString(s) {
		return "'" + strings.Replace(s, "'", "'\"'\"'", -1) + "'"
	}

	return s
}
<commit_msg>Rephrase function doc string<commit_after>// The shellescape package provides the function Quote to escape arbitrary
// strings for a safe use as command line arguments in the most common
// POSIX shells.

package shellescape

import (
	"regexp"
	"strings"
)

var pattern *regexp.Regexp

func init() {
	pattern = regexp.MustCompilePOSIX("[a-zA-Z0-9_^@%+=:,./-]")
}

// Return a shell-escaped version of the string s. The returned value is a
// string that can safely be used as one token in a shell command line.
func Quote(s string) string {
	if len(s) == 0 {
		return "''"
	}
	if pattern.MatchString(s) {
		return "'" + strings.Replace(s, "'", "'\"'\"'", -1) + "'"
	}

	return s
}
<|endoftext|>


<commit_before>/*
Package mote represents a connected Pimoroni Mote device, communicating over USB serial.

It allows you to configure the 4 channels and set individual pixels.

It is a port of the Pimoroni Mote Python library (https://github.com/pimoroni/mote).

The Mote device can be obtained directly from Pimoroni (https://shop.pimoroni.com/products/mote).
*/
package mote

import (
	"fmt"
	"log"

	serial "github.com/johnmccabe/go-serial-native"
)

// __init__
// find_serial_port
// configure_channel
// get_pixel_count
// get_pixel
// set_pixel
// clear
// show

// VID is the USB Vendor ID of the Pimoroni Mote
const VID = 5840

// PID is the USB Product ID of the Pimoroni Mote
const PID = 2244

// ProductName is the USB Product Name of the Pimoroni Mote
const ProductName = "Mote USB Dock"

// MaxPixels is the maximum addressable number of pixels across all channels
const MaxPixels = 512

// MaxPixelsPerChannel is the maximum addressable number of pixels across a single channel
const MaxPixelsPerChannel = int(MaxPixels / 4)

// Mote represents a connected Pimoroni Mote device
type Mote struct {
	PortName string
	Port     *serial.Port
	Channels [4]*Channel
}

// Pixel represents a single RGB pixel
type Pixel struct {
	Red, Green, Blue int
}

// Channel represents a single channel on the Mote board
type Channel struct {
	Pixels          []Pixel
	GammaCorrection bool
}

// NewMote creates a connection to a Mote device, communicating over USB serial.
//
// It will attach to the first available Mote device unless a non-empty string `port_name` is specified at init.
//
//   - portName: override auto-detect and specify an explicit port to use. Must be a complete path ie: /dev/tty.usbmodem1234
func NewMote(portName string) *Mote {
	mote := Mote{
		PortName: portName,
	}
	if mote.PortName == "" {
		mote.PortName = *findSerialPort(VID, PID, ProductName)
	}
	if mote.PortName == "" {
		log.Fatal("unable to detect connected Mote")
	}

	options := serial.RawOptions
	options.Mode = serial.MODE_WRITE
	options.BitRate = 115200
	options.DataBits = 8
	options.Parity = serial.PARITY_NONE
	options.StopBits = 1
	options.FlowControl = 0
	p, err := options.Open(mote.PortName)
	if err != nil {
		panic(err)
	}
	mote.Port = p

	return &mote
}

// ConfigureChannel configures a channel, taking the following parameters.
//
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
//   - numPixels: Number of pixels to configure for this channel
//   - gammaCorrection: Whether to enable gamma correction
func (m *Mote) ConfigureChannel(channel, numPixels int, gammaCorrection bool) error {
	if channel > 4 || channel < 1 {
		return fmt.Errorf("channel index must be between 1 and 4")
	}
	if numPixels > MaxPixelsPerChannel {
		return fmt.Errorf("number of pixels can not be more than %d", MaxPixelsPerChannel)
	}

	p := []Pixel{}
	for i := 0; i < numPixels; i++ {
		p = append(p, Pixel{0, 0, 0})
	}
	c := Channel{
		Pixels:          p,
		GammaCorrection: gammaCorrection,
	}
	m.Channels[channel-1] = &c

	var b []byte
	b = append(b, []byte("mote")...)
	b = append(b, []byte("c")...)
	b = append(b, byte(channel))
	b = append(b, byte(numPixels))
	gammaCorrectionVar := 0
	if gammaCorrection {
		gammaCorrectionVar = 1
	}
	b = append(b, byte(gammaCorrectionVar))

	m.Port.Write(b)
	return nil
}

// SetPixel Set the RGB colour of a single pixel, on a single channel, taking the following parameters.
//
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
//   - index: Index of pixel to set, from 0 up
//   - r: Amount of red: 0-255
//   - g: Amount of green: 0-255
//   - b: Amount of blue: 0-255
func (m *Mote) SetPixel(channel, index, r, g, b int) error {
	if channel > 4 || channel < 1 {
		return fmt.Errorf("channel index must be between 1 and 4")
	}
	if m.Channels[channel-1] == nil {
		return fmt.Errorf("please set up channel %d before using it", channel)
	}
	if index >= len(m.Channels[channel-1].Pixels) {
		return fmt.Errorf("Pixel index must be < %d", m.Channels[channel-1].Pixels)
	}
	m.Channels[channel-1].Pixels[index] = Pixel{r & 0xff, g & 0xff, b & 0xff}
	return nil
}

// Show sends the pixel buffer to the hardware.
func (m *Mote) Show() {
	var b []byte
	b = append(b, []byte("mote")...)
	b = append(b, []byte("o")...)
	for channel, data := range m.Channels {
		if data == nil {
			fmt.Printf("skipping empty channel %d\n", channel+1)
			continue
		}
		for _, pixel := range data.Pixels {
			b = append(b, byte(pixel.Blue))
			b = append(b, byte(pixel.Green))
			b = append(b, byte(pixel.Red))
		}
	}
	m.Port.Write(b)
}

// Clear the buffer of a specific channels, taking the following parameter.
//
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
func (m *Mote) Clear(channel int) error {
	if channel > 4 || channel < 0 {
		return fmt.Errorf("channel index must be between 1 and 4")
	}
	if m.Channels[channel-1] == nil {
		return fmt.Errorf("please set up channel %d before using it", channel)
	}
	for pixel := 0; pixel < 16; pixel++ {
		err := m.SetPixel(channel, pixel, 0, 0, 0)
		if err != nil {
			return err
		}
	}
	return nil
}

// ClearAll clears the buffers of all configured channels.
func (m *Mote) ClearAll() error {
	for channel := 1; channel < 5; channel++ {
		if m.Channels[channel-1] != nil {
			err := m.Clear(channel)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Close closes the serial port connected to the Mote device.
func (m *Mote) Close() {
	log.Printf("Closing port %v\n", m.PortName)
	m.Port.Close()
}

func findSerialPort(v, p int, n string) *string {
	ports, _ := serial.ListPorts()
	if len(ports) == 0 {
		return nil
	}
	for _, info := range ports {
		portName := info.Name()
		if vid, pid, err := info.USBVIDPID(); err == nil {
			if vid == v && pid == p {
				log.Printf("found Mote connected to port: %s\n", portName)
				return &portName
			}
		}
		product := info.USBProduct()
		if product == ProductName {
			log.Printf("found Mote connected to port: %s\n", portName)
			return &portName
		}
	}
	return nil
}
<commit_msg>Add GetPixel/GetPixelCount functions<commit_after>/*
Package mote represents a connected Pimoroni Mote device, communicating over USB serial.

It allows you to configure the 4 channels and set individual pixels.

It is a port of the Pimoroni Mote Python library (https://github.com/pimoroni/mote).

The Mote device can be obtained directly from Pimoroni (https://shop.pimoroni.com/products/mote).
*/
package mote

import (
	"fmt"
	"log"

	serial "github.com/johnmccabe/go-serial-native"
)

// VID is the USB Vendor ID of the Pimoroni Mote
const VID = 5840

// PID is the USB Product ID of the Pimoroni Mote
const PID = 2244

// ProductName is the USB Product Name of the Pimoroni Mote
const ProductName = "Mote USB Dock"

// MaxPixels is the maximum addressable number of pixels across all channels
const MaxPixels = 512

// MaxPixelsPerChannel is the maximum addressable number of pixels across a single channel
const MaxPixelsPerChannel = int(MaxPixels / 4)

// Mote represents a connected Pimoroni Mote device
type Mote struct {
	PortName string
	Port     *serial.Port
	Channels [4]*Channel
}

// Pixel represents a single RGB pixel
type Pixel struct {
	Red, Green, Blue int
}

// Channel represents a single channel on the Mote board
type Channel struct {
	Pixels          []Pixel
	GammaCorrection bool
}

// NewMote creates a connection to a Mote device, communicating over USB serial.
//
// It will attach to the first available Mote device unless a non-empty string `port_name` is specified at init.
//
//   - portName: override auto-detect and specify an explicit port to use. Must be a complete path ie: /dev/tty.usbmodem1234
func NewMote(portName string) *Mote {
	mote := Mote{
		PortName: portName,
	}
	if mote.PortName == "" {
		mote.PortName = *findSerialPort(VID, PID, ProductName)
	}
	if mote.PortName == "" {
		log.Fatal("unable to detect connected Mote")
	}

	options := serial.RawOptions
	options.Mode = serial.MODE_WRITE
	options.BitRate = 115200
	options.DataBits = 8
	options.Parity = serial.PARITY_NONE
	options.StopBits = 1
	options.FlowControl = 0
	p, err := options.Open(mote.PortName)
	if err != nil {
		panic(err)
	}
	mote.Port = p

	return &mote
}

// ConfigureChannel configures a channel, taking the following parameters.
//
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
//   - numPixels: Number of pixels to configure for this channel
//   - gammaCorrection: Whether to enable gamma correction
func (m *Mote) ConfigureChannel(channel, numPixels int, gammaCorrection bool) error {
	if channel > 4 || channel < 1 {
		return fmt.Errorf("channel index must be between 1 and 4")
	}
	if numPixels > MaxPixelsPerChannel {
		return fmt.Errorf("number of pixels can not be more than %d", MaxPixelsPerChannel)
	}

	p := []Pixel{}
	for i := 0; i < numPixels; i++ {
		p = append(p, Pixel{0, 0, 0})
	}
	c := Channel{
		Pixels:          p,
		GammaCorrection: gammaCorrection,
	}
	m.Channels[channel-1] = &c

	var b []byte
	b = append(b, []byte("mote")...)
	b = append(b, []byte("c")...)
	b = append(b, byte(channel))
	b = append(b, byte(numPixels))
	gammaCorrectionVar := 0
	if gammaCorrection {
		gammaCorrectionVar = 1
	}
	b = append(b, byte(gammaCorrectionVar))

	m.Port.Write(b)
	return nil
}

// SetPixel Set the RGB colour of a single pixel, on a single channel, taking the following parameters.
//
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
//   - index: Index of pixel to set, from 0 up
//   - r: Amount of red: 0-255
//   - g: Amount of green: 0-255
//   - b: Amount of blue: 0-255
func (m *Mote) SetPixel(channel, index, r, g, b int) error {
	if channel > 4 || channel < 1 {
		return fmt.Errorf("channel index must be between 1 and 4")
	}
	if m.Channels[channel-1] == nil {
		return fmt.Errorf("please set up channel %d before using it", channel)
	}
	if index >= len(m.Channels[channel-1].Pixels) {
		return fmt.Errorf("Pixel index must be < %d", m.Channels[channel-1].Pixels)
	}
	m.Channels[channel-1].Pixels[index] = Pixel{r & 0xff, g & 0xff, b & 0xff}
	return nil
}

// Show sends the pixel buffer to the hardware.
func (m *Mote) Show() {
	var b []byte
	b = append(b, []byte("mote")...)
	b = append(b, []byte("o")...)
	for channel, data := range m.Channels {
		if data == nil {
			fmt.Printf("skipping empty channel %d\n", channel+1)
			continue
		}
		for _, pixel := range data.Pixels {
			b = append(b, byte(pixel.Blue))
			b = append(b, byte(pixel.Green))
			b = append(b, byte(pixel.Red))
		}
	}
	m.Port.Write(b)
}

// Clear the buffer of a specific channels, taking the following parameter.
//
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
func (m *Mote) Clear(channel int) error {
	if channel > 4 || channel < 0 {
		return fmt.Errorf("channel index must be between 1 and 4")
	}
	if m.Channels[channel-1] == nil {
		return fmt.Errorf("please set up channel %d before using it", channel)
	}
	for pixel := 0; pixel < 16; pixel++ {
		err := m.SetPixel(channel, pixel, 0, 0, 0)
		if err != nil {
			return err
		}
	}
	return nil
}

// ClearAll clears the buffers of all configured channels.
func (m *Mote) ClearAll() error {
	for channel := 1; channel < 5; channel++ {
		if m.Channels[channel-1] != nil {
			err := m.Clear(channel)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Close closes the serial port connected to the Mote device.
func (m *Mote) Close() {
	log.Printf("Closing port %v\n", m.PortName)
	m.Port.Close()
}

// GetPixelCount gets the number of pixels a channel is configured to use, taking the following parameters.
//   - channel: Channel, either 1, 2 3 or 4 corresponding to numbers on Mote
func (m *Mote) GetPixelCount(channel int) (int, error) {
	if channel > 4 || channel < 1 {
		return 0, fmt.Errorf("channel index must be between 1 and 4")
	}
	if m.Channels[channel-1] == nil {
		return 0, fmt.Errorf("channel %d has not been set up", channel)
	}
	return len(m.Channels[channel-1].Pixels), nil
}

// GetPixel gets the RGB colour of a single pixel, on a single channel, taking the following parameters.
//   - channel: Channel, either 1, 2, 3 or 4 corresponding to numbers on Mote
//   - index: Index of pixel to set, from 0 up
func (m *Mote) GetPixel(channel, index int) (Pixel, error) {
	if channel > 4 || channel < 1 {
		return Pixel{}, fmt.Errorf("channel index must be between 1 and 4")
	}
	if m.Channels[channel-1] == nil {
		return Pixel{}, fmt.Errorf("channel %d has not been set up", channel)
	}
	if index >= len(m.Channels[channel-1].Pixels) {
		return Pixel{}, fmt.Errorf("pixel index must be < %d", len(m.Channels[channel-1].Pixels))
	}
	return m.Channels[channel-1].Pixels[index], nil
}

func findSerialPort(v, p int, n string) *string {
	ports, _ := serial.ListPorts()
	if len(ports) == 0 {
		return nil
	}
	for _, info := range ports {
		portName := info.Name()
		if vid, pid, err := info.USBVIDPID(); err == nil {
			if vid == v && pid == p {
				log.Printf("found Mote connected to port: %s\n", portName)
				return &portName
			}
		}
		product := info.USBProduct()
		if product == ProductName {
			log.Printf("found Mote connected to port: %s\n", portName)
			return &portName
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"path/filepath"
	"runtime"

	"github.com/NebulousLabs/Sia/api"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/consensus"
	"github.com/NebulousLabs/Sia/modules/explorer"
	"github.com/NebulousLabs/Sia/modules/gateway"

	"github.com/spf13/cobra"
)

// startDaemonCmd uses the config parameters to start siad.
func startDaemon() error {
	// Establish multithreading.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Create all of the modules.
	gateway, err := gateway.New(config.Siad.RPCaddr, filepath.Join(config.Siad.SiaDir, modules.GatewayDir))
	if err != nil {
		return err
	}
	state, err := consensus.New(gateway, filepath.Join(config.Siad.SiaDir, modules.ConsensusDir))
	if err != nil {
		return err
	}
	explorer, err := explorer.New(state, filepath.Join(config.Siad.SiaDir, modules.ExplorerDir))
	if err != nil {
		return err
	}
	srv, err := api.NewServer(config.Siad.APIaddr, state, gateway, nil, nil, nil, nil, nil, nil, explorer)
	if err != nil {
		return err
	}

	// Bootstrap to the network.
	if !config.Siad.NoBootstrap {
		for i := range modules.BootstrapPeers {
			go gateway.Connect(modules.BootstrapPeers[i])
		}
	}

	// Send a struct down the started channel, so the testing package knows
	// that daemon startup has completed. A gofunc is used with the hope that
	// srv.Serve() will start running before the value is sent down the
	// channel.
	go func() {
		started <- struct{}{}
	}()

	// Start serving api requests.
	err = srv.Serve()
	if err != nil {
		return err
	}
	return nil
}

// startDaemonCmd is a passthrough function for startDaemon.
func startDaemonCmd(*cobra.Command, []string) {
	err := startDaemon()
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>Give siae a hostdb module<commit_after>package main

import (
	"fmt"
	"path/filepath"
	"runtime"

	"github.com/NebulousLabs/Sia/api"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/consensus"
	"github.com/NebulousLabs/Sia/modules/explorer"
	"github.com/NebulousLabs/Sia/modules/gateway"
	"github.com/NebulousLabs/Sia/modules/hostdb"

	"github.com/spf13/cobra"
)

// startDaemonCmd uses the config parameters to start siad.
func startDaemon() error {
	// Establish multithreading.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Create all of the modules.
	gateway, err := gateway.New(config.Siad.RPCaddr, filepath.Join(config.Siad.SiaDir, modules.GatewayDir))
	if err != nil {
		return err
	}
	state, err := consensus.New(gateway, filepath.Join(config.Siad.SiaDir, modules.ConsensusDir))
	if err != nil {
		return err
	}
	hostdb, err := hostdb.New(state, gateway)
	if err != nil {
		return err
	}
	explorer, err := explorer.New(state, filepath.Join(config.Siad.SiaDir, modules.ExplorerDir))
	if err != nil {
		return err
	}
	srv, err := api.NewServer(config.Siad.APIaddr, state, gateway, nil, hostdb, nil, nil, nil, nil, explorer)
	if err != nil {
		return err
	}

	// Bootstrap to the network.
	if !config.Siad.NoBootstrap {
		for i := range modules.BootstrapPeers {
			go gateway.Connect(modules.BootstrapPeers[i])
		}
	}

	// Send a struct down the started channel, so the testing package knows
	// that daemon startup has completed. A gofunc is used with the hope that
	// srv.Serve() will start running before the value is sent down the
	// channel.
	go func() {
		started <- struct{}{}
	}()

	// Start serving api requests.
	err = srv.Serve()
	if err != nil {
		return err
	}
	return nil
}

// startDaemonCmd is a passthrough function for startDaemon.
func startDaemonCmd(*cobra.Command, []string) {
	err := startDaemon()
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// this will store notes in ~/notes if the NOGODIR environment variable isn't
// set
var NotesSubDir = "notes"

// this will be used as the default editor if the EDITOR environment variable
// isn't set
var DefaultEditor = "vim"

var helpText = `
nogo - the notes helper

actions:
  nogo new
  nogo new [topic]
  nogo new [topic] [event]
  nogo ls
  nogo ls [topic]
  nogo edit [topic] [note name substring]
`

var directory string
var editor string

func init() {
	directory = os.Getenv("NOGODIR")
	if directory == "" {
		directory = fmt.Sprintf("%s/%s", os.Getenv("HOME"), NotesSubDir)
	}

	editor = os.Getenv("EDITOR")
	if editor == "" {
		editor = DefaultEditor
	}
}

func help(exit int) {
	fmt.Println(helpText)
	os.Exit(exit)
}

func acceptInput(question string) string {
	reader := bufio.NewReader(os.Stdin)

	fmt.Print(question)
	response, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("Oops, what was that?")
		os.Exit(1)
	}

	return strings.TrimSpace(response)
}

func normalizeString(s *string) {
	*s = strings.Replace(*s, " ", "-", -1)
}

func openFile(fileName string) {
	cmd := exec.Command(editor, fileName)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		fmt.Println("Couldn't open the file:", err)
		os.Exit(1)
	}
}

func createFile(fileName string) {
	_, err := os.Create(fileName)
	if err != nil {
		fmt.Println("Oops, I couldn't create the file:", fileName)
	}
}

func createDir(dirName string) {
	err := os.MkdirAll(dirName, 0755)
	if err != nil {
		fmt.Println("Oops, I couldn't make the directory:", dirName)
		os.Exit(1)
	}
}

func gatherFiles() {
	files := []string{}
	visit := func(path string, f os.FileInfo, err error) error {
		files = append(files, path)
		return nil
	}
	filepath.Walk(directory, visit)
	fmt.Println(files)

}

func handleNew() {
	// Ask for the topic of notes
	topic := acceptInput("Enter the notes topic: ")
	normalizeString(&topic)

	handleNewTopic(topic)
}

func handleNewTopic(topic string) {
	// Ask for the event name of the notes
	event := acceptInput("Enter the event name: ")
	normalizeString(&event)

	handleNewEvent(topic, event)
}

func handleNewEvent(topic, event string) {
	// Create the topic folder if it doesn't exist
	notesDirectory := filepath.Join(directory, topic)
	createDir(notesDirectory)

	// Make the filename and filepath for the new notes file
	fileName := fmt.Sprintf("%s.md", event)
	fullPath := filepath.Join(notesDirectory, fileName)

	// Create the new notes file
	createFile(fullPath)

	// Open the new file in your editor of choice
	openFile(fullPath)
}

func parseFilename(filename string) string {
	return strings.TrimSuffix(filename, ".md")
}

func isDir(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}
	defer f.Close()
	fi, err := f.Stat()
	if err != nil {
		return false
	}
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return true
	case mode.IsRegular():
		return false
	default:
		return false
	}

}

func listTopics() {
	files, err := ioutil.ReadDir(directory)
	if err != nil {
		fmt.Println("Oops, couldn't read that directory:", directory)
		os.Exit(1)
	}

	fmt.Println()

	toPrint := []string{}
	for _, file := range files {
		path := fmt.Sprintf("%s/%s", directory, file.Name())
		if isDir(path) && !strings.HasPrefix(file.Name(), ".git") {
			toPrint = append(toPrint, file.Name())
		}
	}

	if len(toPrint) == 0 {
		fmt.Println("looks like there aren't any topcis to list!")
	} else {
		fmt.Println("all topics:")
	}

	for _, file := range toPrint {
		fmt.Println("  ", file)
	}
	fmt.Println()
}

func listNotes(topic string) {
	topicDir := fmt.Sprintf("%s/%s", directory, topic)
	files, err := ioutil.ReadDir(topicDir)
	if err != nil {
		fmt.Println("Oops, couldn't read that directory:", topicDir)
		os.Exit(1)
	}

	fmt.Println()
	if len(files) == 0 {
		fmt.Println("looks like there aren't any notes to list!")
	} else {
		fmt.Printf("notes in %s:\n", topic)
	}

	for _, file := range files {
		fmt.Println("  ", parseFilename(file.Name()))
	}

	fmt.Println()

}

func editFile(topic, target string) {
	topicDir := fmt.Sprintf("%s/%s", directory, topic)
	files, err := ioutil.ReadDir(topicDir)
	if err != nil {
		fmt.Println("Oops, couldn't read that directory:", topicDir)
	}

	target = strings.Replace(target, " ", "-", -1)
	var found bool

	for _, file := range files {
		if strings.Contains(file.Name(), target) {
			found = true
			fullPath := fmt.Sprintf("%s/%s/%s", directory, topic, file.Name())
			openFile(fullPath)
		}
	}

	if !found {
		fmt.Println("Oops, couldn't find that file!")
		os.Exit(1)
	}
}

func main() {
	if len(os.Args) == 1 {
		help(0)
	}
	action := os.Args[1]

	switch action {
	case "new":
		if len(os.Args) == 2 {
			handleNew()
		} else if len(os.Args) == 3 {
			handleNewTopic(os.Args[2])
		} else if len(os.Args) == 4 {
			handleNewEvent(os.Args[2], os.Args[3])
		} else {
			help(1)
		}
	case "ls":
		if len(os.Args) == 2 {
			listTopics()
		} else if len(os.Args) == 3 {
			listNotes(os.Args[2])
		} else {
			help(1)
		}
	case "edit":
		if len(os.Args) < 4 {
			fmt.Println("I need a topic and a note to edit!")
			os.Exit(1)
		}
		editFile(os.Args[2], strings.Join(os.Args[3:], " "))
	default:
		help(0)
	}
}
<commit_msg>better handling for whitespace and autocomplete<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// this will store notes in ~/notes if the NOGODIR environment variable isn't
// set
var NotesSubDir = "notes"

// this will be used as the default editor if the EDITOR environment variable
// isn't set
var DefaultEditor = "vim"

var helpText = `
nogo - the notes helper

actions:
  nogo new
  nogo new [topic]
  nogo new [topic] [event]
  nogo ls
  nogo ls [topic]
  nogo edit [topic] [note name substring]
`

var directory string
var editor string

func init() {
	directory = os.Getenv("NOGODIR")
	if directory == "" {
		directory = fmt.Sprintf("%s/%s", os.Getenv("HOME"), NotesSubDir)
	}

	editor = os.Getenv("EDITOR")
	if editor == "" {
		editor = DefaultEditor
	}
}

func help(exit int) {
	fmt.Println(helpText)
	os.Exit(exit)
}

func acceptInput(question string) string {
	reader := bufio.NewReader(os.Stdin)

	fmt.Print(question)
	response, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("Oops, what was that?")
		os.Exit(1)
	}

	return strings.TrimSpace(response)
}

func normalizeString(s *string) {
	*s = strings.Replace(*s, " ", "-", -1)
}

func openFile(fileName string) {
	cmd := exec.Command(editor, fileName)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		fmt.Println("Couldn't open the file:", err)
		os.Exit(1)
	}
}

func createFile(fileName string) {
	_, err := os.Create(fileName)
	if err != nil {
		fmt.Println("Oops, I couldn't create the file:", fileName)
	}
}

func createDir(dirName string) {
	err := os.MkdirAll(dirName, 0755)
	if err != nil {
		fmt.Println("Oops, I couldn't make the directory:", dirName)
		os.Exit(1)
	}
}

func gatherFiles() {
	files := []string{}
	visit := func(path string, f os.FileInfo, err error) error {
		files = append(files, path)
		return nil
	}
	filepath.Walk(directory, visit)
	fmt.Println(files)

}

func handleNew() {
	// Ask for the topic of notes
	topic := acceptInput("Enter the notes topic: ")
	normalizeString(&topic)

	handleNewTopic(topic)
}

func handleNewTopic(topic string) {
	// Ask for the event name of the notes
	event := acceptInput("Enter the event name: ")
	normalizeString(&event)

	handleNewEvent(topic, event)
}

func handleNewEvent(topic, event string) {
	// Create the topic folder if it doesn't exist
	notesDirectory := filepath.Join(directory, topic)
	createDir(notesDirectory)

	// Make the filename and filepath for the new notes file
	fileName := fmt.Sprintf("%s.md", event)
	fullPath := filepath.Join(notesDirectory, fileName)

	// Create the new notes file
	createFile(fullPath)

	// Open the new file in your editor of choice
	openFile(fullPath)
}

func parseFilename(filename string) string {
	return strings.Replace(strings.TrimSuffix(filename, ".md"), "-", " ", -1)
}

func isDir(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}
	defer f.Close()
	fi, err := f.Stat()
	if err != nil {
		return false
	}
	switch mode := fi.Mode(); {
	case mode.IsDir():
		return true
	case mode.IsRegular():
		return false
	default:
		return false
	}

}

func listTopics() {
	files, err := ioutil.ReadDir(directory)
	if err != nil {
		fmt.Println("Oops, couldn't read that directory:", directory)
		os.Exit(1)
	}

	fmt.Println()

	toPrint := []string{}
	for _, file := range files {
		path := fmt.Sprintf("%s/%s", directory, file.Name())
		if isDir(path) && !strings.HasPrefix(file.Name(), ".git") {
			toPrint = append(toPrint, file.Name())
		}
	}

	if len(toPrint) == 0 {
		fmt.Println("looks like there aren't any topcis to list!")
	} else {
		fmt.Println("all topics:")
	}

	for _, file := range toPrint {
		fmt.Println("  ", file)
	}
	fmt.Println()
}

func findTopicBySubstring(substring string) (string, error) {
	topics, err := ioutil.ReadDir(directory)
	if err != nil {
		return "", err
	}
	for _, topic := range topics {
		if strings.Contains(topic.Name(), substring) {
			return topic.Name(), nil
		}
	}

	return "", errors.New("Couldn't find that filename")
}

func listNotes(topic string) {
	completeTopic, err := findTopicBySubstring(topic)
	if err != nil {
		fmt.Println("Oops, couldn't find that topic:", topic)
		os.Exit(1)
	}
	topicDir := fmt.Sprintf("%s/%s", directory, completeTopic)
	files, err := ioutil.ReadDir(topicDir)
	if err != nil {
		fmt.Println("Oops, couldn't read that directory:", topicDir)
		os.Exit(1)
	}

	fmt.Println()
	if len(files) == 0 {
		fmt.Println("looks like there aren't any notes to list!")
	} else {
		fmt.Printf("notes in %s:\n", completeTopic)
	}

	for _, file := range files {
		fmt.Println("  ", parseFilename(file.Name()))
	}

	fmt.Println()

}

func editFile(topic, target string) {
	completeTopic, err := findTopicBySubstring(topic)
	if err != nil {
		fmt.Println("Oops, couldn't find that topic:", topic)
		os.Exit(1)
	}
	topicDir := fmt.Sprintf("%s/%s", directory, completeTopic)
	files, err := ioutil.ReadDir(topicDir)
	if err != nil {
		fmt.Println("Oops, couldn't read that directory:", topicDir)
		os.Exit(1)
	}

	target = strings.Replace(target, " ", "-", -1)
	var found bool

	for _, file := range files {
		if strings.Contains(file.Name(), target) {
			found = true
			fullPath := fmt.Sprintf("%s/%s/%s", directory, completeTopic, file.Name())
			openFile(fullPath)
		}
	}

	if !found {
		fmt.Println("Oops, couldn't find that file!")
		os.Exit(1)
	}
}

func main() {
	if len(os.Args) == 1 {
		help(0)
	}
	action := os.Args[1]

	switch action {
	case "new":
		if len(os.Args) == 2 {
			handleNew()
		} else if len(os.Args) == 3 {
			handleNewTopic(os.Args[2])
		} else if len(os.Args) == 4 {
			handleNewEvent(os.Args[2], os.Args[3])
		} else {
			help(1)
		}
	case "ls":
		if len(os.Args) == 2 {
			listTopics()
		} else if len(os.Args) == 3 {
			listNotes(os.Args[2])
		} else {
			help(1)
		}
	case "edit":
		if len(os.Args) < 4 {
			fmt.Println("I need a topic and a note to edit!")
			os.Exit(1)
		}
		editFile(os.Args[2], strings.Join(os.Args[3:], "-"))
	default:
		help(0)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"github.com/fabiofalci/sconsify/spotify"
	sp "github.com/op/go-libspotify/spotify"
)

func main() {
	initialised := make(chan bool)
	status := make(chan string)
	toPlay := make(chan sp.Track)
	nextPlay := make(chan string)

	go spotify.Initialise(initialised, toPlay, nextPlay, status)

	<-initialised

	playlist := spotify.Playlists["Ramones"]
	playlist.Wait()
	track := playlist.Track(3).Track()
	track.Wait()

	toPlay <- *track

	println(track.Name())

	for {
		time.Sleep(100 * time.Millisecond)
	}
}
<commit_msg>Remove nogui.go test class<commit_after><|endoftext|>


<commit_before>package coup

import "fmt"

type MoveEnum int

const (
	Income      MoveEnum = iota
	ForeignAid           = iota
	Coup                 = iota
	Tax                  = iota
	Assassinate          = iota
	Exchange             = iota
	Steal                = iota
)

type Move struct {
	Case      MoveEnum
	Subject   *Player
	Object    *Player
	Challenge *Challenge
	Block     *Block
}

func NewIncome(sub *Player) *Move {
	return &Move{
		Case:    Income,
		Subject: sub,
	}
}

func NewForeignAid(sub *Player) *Move {
	return &Move{
		Case:    ForeignAid,
		Subject: sub,
	}
}

func NewCoup(sub *Player, obj *Player) *Move {
	return &Move{
		Case:    Coup,
		Subject: sub,
		Object:  obj,
	}
}

func NewTax(sub *Player) *Move {
	return &Move{
		Case:    Tax,
		Subject: sub,
	}
}

func NewAssassinate(sub *Player, obj *Player) *Move {
	return &Move{
		Case:    Assassinate,
		Subject: sub,
		Object:  obj,
	}
}

func NewExchange(sub *Player) *Move {
	return &Move{
		Case:    Exchange,
		Subject: sub,
	}
}

func NewSteal(sub *Player, obj *Player) *Move {
	return &Move{
		Case:    Steal,
		Subject: sub,
		Object:  obj,
	}
}

func (m *Move) Modify(gm *Game) {

	// TODO: Return this
	for _, player := range gm.Players {
		if player.Hand.Size() > 2 {
			for _, card := range player.Discard(gm, 2) {
				gm.Deck.Add(card)
			}
		}
	}

	switch m.Case {
	case Coup:
		m.Subject.Coins -= 7
	case Assassinate:
		m.Subject.Coins -= 3
	}

	if gm.Logs {
		switch m.Case {
		case Income:
			fmt.Printf("%s takes income.\n", m.Subject.Name)
		case ForeignAid:
			fmt.Printf("%s takes foreign aid.\n", m.Subject.Name)
		case Coup:
			fmt.Printf("%s coups %s.\n", m.Subject.Name, m.Object.Name)
		case Tax:
			fmt.Printf("%s taxes.\n", m.Subject.Name)
		case Assassinate:
			fmt.Printf("%s assassinates %s.\n", m.Subject.Name, m.Object.Name)
		case Exchange:
			fmt.Printf("%s exchanges.\n", m.Subject.Name)
		case Steal:
			fmt.Printf("%s steals from %s.\n", m.Subject.Name, m.Object.Name)
		}
	}

	exposed := m.Exposed(gm)

	if !exposed && m.Case == Exchange {
		// TODO: return this home
		if m.Case == Exchange {
			m.Subject.Draw(gm.Deck)
			m.Subject.Draw(gm.Deck)
		}
	}

	if exposed {
		for _, player := range gm.Players {
			player.Observe(gm, m, nil, false)
		}
		return
	}

	switch m.Case {
	case ForeignAid, Assassinate, Steal:
		for _, player := range gm.Players {
			player.Observe(gm, m, nil, true)
		}
	}

	alive := 0
	for _, player := range gm.Players {
		if player.Alive() {
			alive++
		}
	}

	if alive < 2 {
		return
	}

	blocked := m.Blocked(gm)

	if !blocked {
		switch m.Case {
		case Income:
			m.Subject.Coins++
		case ForeignAid:
			m.Subject.Coins += 2
		case Coup:
			for _, card := range m.Object.Discard(gm, 1) {
				gm.Discard.Add(card)
			}
		case Tax:
			m.Subject.Coins += 3
		case Assassinate:
			if m.Object.Alive() {
				for _, card := range m.Object.Discard(gm, 1) {
					gm.Discard.Add(card)
				}
			}
		case Exchange:
			// TODO: return to here
		case Steal:
			amt := 2

			if m.Object.Coins < 2 {
				amt = m.Object.Coins
			}

			m.Subject.Coins += amt
			m.Object.Coins -= amt
		}

		if gm.Logs {
			switch m.Case {
			case Income:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
			case ForeignAid:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
			case Coup:
				fmt.Printf("%s discards.\n", m.Object.Name)
			case Tax:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
			case Assassinate:
				fmt.Printf("%s potentially discards.\n", m.Object.Name)
			case Exchange:
				fmt.Printf("%s draws two cards.\n", m.Subject.Name)
			case Steal:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
				fmt.Printf("%s has %d coins.\n", m.Object.Name, m.Object.Coins)
			}
		}
	}

	for _, player := range gm.Players {
		player.Observe(gm, nil, m.Block, false)
	}

}

func (m *Move) Exposed(gm *Game) bool {
	var claim *Claim
	switch m.Case {
	case Tax:
		claim = NewClaim(m.Subject, Duke)
	case Assassinate:
		claim = NewClaim(m.Subject, Assassin)
	case Exchange:
		claim = NewClaim(m.Subject, Ambassador)
	case Steal:
		claim = NewClaim(m.Subject, Captain)
	}

	if claim == nil {
		return false
	}

	var exposed bool
	for _, other := range m.Subject.Opponents(gm) {
		if m.Challenge = other.ChallengeMove(gm, claim, m.Object); m.Challenge != nil {
			if gm.Logs {
				fmt.Printf("%s challenges.\n", m.Challenge.Subject.Name)
			}
			if claim.Verify() {
				if gm.Logs {
					fmt.Printf("Challenge unsuccessful.\n")
				}
				for _, card := range m.Challenge.Subject.Discard(gm, 1) {
					gm.Discard.Add(card)
				}
				m.Subject.Hand.Remove(claim.Declared)
				gm.Deck.Add(claim.Declared)
				card := gm.Deck.Peek()
				gm.Deck.Remove(card)
				m.Subject.Hand.Add(card)
			} else {
				if gm.Logs {
					fmt.Printf("Challenge successful.\n")
				}
				for _, card := range m.Subject.Discard(gm, 1) {
					gm.Discard.Add(card)
				}
				exposed = true
			}
			break
		}
	}

	return exposed
}

func (m *Move) Blocked(gm *Game) bool {
	switch m.Case {
	case ForeignAid:
		for _, other := range m.Subject.Opponents(gm) {
			m.Block = other.Block(gm, m)
			if m.Block != nil {
				break
			}
		}
	case Assassinate:
		if m.Object.Alive() {
			m.Block = m.Object.Block(gm, m)
		}
	case Steal:
		if m.Object.Alive() {
			m.Block = m.Object.Block(gm, m)
		}
	}

	var blocked bool
	if m.Block != nil {
		if gm.Logs {
			fmt.Printf("%s blocks.\n", m.Block.Subject.Name)
		}
		if !m.Block.Exposed(gm) {
			blocked = true
		}
	}

	return blocked
}
<commit_msg>More Appropriate Fix<commit_after>package coup

import "fmt"

type MoveEnum int

const (
	Income      MoveEnum = iota
	ForeignAid           = iota
	Coup                 = iota
	Tax                  = iota
	Assassinate          = iota
	Exchange             = iota
	Steal                = iota
)

type Move struct {
	Case      MoveEnum
	Subject   *Player
	Object    *Player
	Challenge *Challenge
	Block     *Block
}

func NewIncome(sub *Player) *Move {
	return &Move{
		Case:    Income,
		Subject: sub,
	}
}

func NewForeignAid(sub *Player) *Move {
	return &Move{
		Case:    ForeignAid,
		Subject: sub,
	}
}

func NewCoup(sub *Player, obj *Player) *Move {
	return &Move{
		Case:    Coup,
		Subject: sub,
		Object:  obj,
	}
}

func NewTax(sub *Player) *Move {
	return &Move{
		Case:    Tax,
		Subject: sub,
	}
}

func NewAssassinate(sub *Player, obj *Player) *Move {
	return &Move{
		Case:    Assassinate,
		Subject: sub,
		Object:  obj,
	}
}

func NewExchange(sub *Player) *Move {
	return &Move{
		Case:    Exchange,
		Subject: sub,
	}
}

func NewSteal(sub *Player, obj *Player) *Move {
	return &Move{
		Case:    Steal,
		Subject: sub,
		Object:  obj,
	}
}

func (m *Move) Modify(gm *Game) {

	// TODO: Return this
	for _, player := range gm.Players {
		if player.Hand.Size() > 2 {
			for _, card := range player.Discard(gm, 2) {
				gm.Deck.Add(card)
			}
		}
	}

	switch m.Case {
	case Coup:
		m.Subject.Coins -= 7
	case Assassinate:
		m.Subject.Coins -= 3
	}

	if gm.Logs {
		switch m.Case {
		case Income:
			fmt.Printf("%s takes income.\n", m.Subject.Name)
		case ForeignAid:
			fmt.Printf("%s takes foreign aid.\n", m.Subject.Name)
		case Coup:
			fmt.Printf("%s coups %s.\n", m.Subject.Name, m.Object.Name)
		case Tax:
			fmt.Printf("%s taxes.\n", m.Subject.Name)
		case Assassinate:
			fmt.Printf("%s assassinates %s.\n", m.Subject.Name, m.Object.Name)
		case Exchange:
			fmt.Printf("%s exchanges.\n", m.Subject.Name)
		case Steal:
			fmt.Printf("%s steals from %s.\n", m.Subject.Name, m.Object.Name)
		}
	}

	exposed := m.Exposed(gm)

	if !exposed && m.Case == Exchange {
		// TODO: return this home
		if m.Case == Exchange {
			m.Subject.Draw(gm.Deck)
			m.Subject.Draw(gm.Deck)
		}
	}

	if exposed {
		for _, player := range gm.Players {
			player.Observe(gm, m, nil, false)
		}
		return
	}

	switch m.Case {
	case ForeignAid, Assassinate, Steal:
		for _, player := range gm.Players {
			player.Observe(gm, m, nil, true)
		}
	}

	blocked := m.Blocked(gm)

	if !blocked {
		switch m.Case {
		case Income:
			m.Subject.Coins++
		case ForeignAid:
			m.Subject.Coins += 2
		case Coup:
			for _, card := range m.Object.Discard(gm, 1) {
				gm.Discard.Add(card)
			}
		case Tax:
			m.Subject.Coins += 3
		case Assassinate:
			if m.Object.Alive() {
				for _, card := range m.Object.Discard(gm, 1) {
					gm.Discard.Add(card)
				}
			}
		case Exchange:
			// TODO: return to here
		case Steal:
			amt := 2

			if m.Object.Coins < 2 {
				amt = m.Object.Coins
			}

			m.Subject.Coins += amt
			m.Object.Coins -= amt
		}

		if gm.Logs {
			switch m.Case {
			case Income:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
			case ForeignAid:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
			case Coup:
				fmt.Printf("%s discards.\n", m.Object.Name)
			case Tax:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
			case Assassinate:
				fmt.Printf("%s potentially discards.\n", m.Object.Name)
			case Exchange:
				fmt.Printf("%s draws two cards.\n", m.Subject.Name)
			case Steal:
				fmt.Printf("%s has %d coins.\n", m.Subject.Name, m.Subject.Coins)
				fmt.Printf("%s has %d coins.\n", m.Object.Name, m.Object.Coins)
			}
		}
	}

	for _, player := range gm.Players {
		switch m.Case {
		case Income, Coup, Tax, Exchange:
			player.Observe(gm, m, nil, false)
		case ForeignAid, Assassinate, Steal:
			player.Observe(gm, nil, m.Block, false)
		}
	}

}

func (m *Move) Exposed(gm *Game) bool {
	var claim *Claim
	switch m.Case {
	case Tax:
		claim = NewClaim(m.Subject, Duke)
	case Assassinate:
		claim = NewClaim(m.Subject, Assassin)
	case Exchange:
		claim = NewClaim(m.Subject, Ambassador)
	case Steal:
		claim = NewClaim(m.Subject, Captain)
	}

	if claim == nil {
		return false
	}

	var exposed bool
	for _, other := range m.Subject.Opponents(gm) {
		if m.Challenge = other.ChallengeMove(gm, claim, m.Object); m.Challenge != nil {
			if gm.Logs {
				fmt.Printf("%s challenges.\n", m.Challenge.Subject.Name)
			}
			if claim.Verify() {
				if gm.Logs {
					fmt.Printf("Challenge unsuccessful.\n")
				}
				for _, card := range m.Challenge.Subject.Discard(gm, 1) {
					gm.Discard.Add(card)
				}
				m.Subject.Hand.Remove(claim.Declared)
				gm.Deck.Add(claim.Declared)
				card := gm.Deck.Peek()
				gm.Deck.Remove(card)
				m.Subject.Hand.Add(card)
			} else {
				if gm.Logs {
					fmt.Printf("Challenge successful.\n")
				}
				for _, card := range m.Subject.Discard(gm, 1) {
					gm.Discard.Add(card)
				}
				exposed = true
			}
			break
		}
	}

	return exposed
}

func (m *Move) Blocked(gm *Game) bool {
	switch m.Case {
	case ForeignAid:
		for _, other := range m.Subject.Opponents(gm) {
			m.Block = other.Block(gm, m)
			if m.Block != nil {
				break
			}
		}
	case Assassinate:
		if m.Object.Alive() {
			m.Block = m.Object.Block(gm, m)
		}
	case Steal:
		if m.Object.Alive() {
			m.Block = m.Object.Block(gm, m)
		}
	}

	var blocked bool
	if m.Block != nil {
		if gm.Logs {
			fmt.Printf("%s blocks.\n", m.Block.Subject.Name)
		}
		if !m.Block.Exposed(gm) {
			blocked = true
		}
	}

	return blocked
}
<|endoftext|>


<commit_before>package nopaste

import (
	"log"
	"net/http"
)

const MsgrRoot = "/irc-msgr"

func RunMsgr(configFile string) error {
	var err error
	config, err = LoadConfig(configFile)
	if err != nil {
		return err
	}
	var chs []MessageChan
	if config.IRC != nil {
		ircCh := make(IRCMessageChan, MsgBufferLen)
		chs = append(chs, ircCh)
		go RunIRCAgent(config, ircCh)
	}
	if config.Slack != nil {
		slackCh := make(SlackMessageChan, MsgBufferLen)
		chs = append(chs, slackCh)
		go RunSlackAgent(config, slackCh)
	}
	http.HandleFunc(MsgrRoot+"/post", func(w http.ResponseWriter, req *http.Request) {
		msgrPostHandler(w, req, chs)
	})
	log.Fatal(http.ListenAndServe(config.Listen, nil))
	return nil
}

func msgrPostHandler(w http.ResponseWriter, req *http.Request, chs []MessageChan) {
	channel := req.FormValue("channel")
	msg := req.FormValue("msg")
	if channel == "" || msg == "" || req.Method != "POST" {
		code := http.StatusBadRequest
		http.Error(w, http.StatusText(code), code)
		return
	}
	for _, ch := range chs {
		ch.PostMsgr(req)
	}
	code := http.StatusCreated
	http.Error(w, http.StatusText(code), code)
}
<commit_msg>not send response body when code==201<commit_after>package nopaste

import (
	"log"
	"net/http"
)

const MsgrRoot = "/irc-msgr"

func RunMsgr(configFile string) error {
	var err error
	config, err = LoadConfig(configFile)
	if err != nil {
		return err
	}
	var chs []MessageChan
	if config.IRC != nil {
		ircCh := make(IRCMessageChan, MsgBufferLen)
		chs = append(chs, ircCh)
		go RunIRCAgent(config, ircCh)
	}
	if config.Slack != nil {
		slackCh := make(SlackMessageChan, MsgBufferLen)
		chs = append(chs, slackCh)
		go RunSlackAgent(config, slackCh)
	}
	http.HandleFunc(MsgrRoot+"/post", func(w http.ResponseWriter, req *http.Request) {
		msgrPostHandler(w, req, chs)
	})
	log.Fatal(http.ListenAndServe(config.Listen, nil))
	return nil
}

func msgrPostHandler(w http.ResponseWriter, req *http.Request, chs []MessageChan) {
	channel := req.FormValue("channel")
	msg := req.FormValue("msg")
	if channel == "" || msg == "" || req.Method != "POST" {
		code := http.StatusBadRequest
		http.Error(w, http.StatusText(code), code)
		return
	}
	for _, ch := range chs {
		ch.PostMsgr(req)
	}
	w.WriteHeader(http.StatusCreated)
	w.Write([]byte{})
}
<|endoftext|>


<commit_before>// 27 september 2014

package main

import (
	// ...
)

type MSVC struct			{                                         }

// TODO /MDd, /MTd

func (m *MSVC) buildRegularFile(std string, cflags []string, filename string) (stages []Stage, object string) {
	object = objectName(filename, ".o")
	line := append([]string{
		"cl",
		filename,
		"/c",
		std,
		"/analyze",
		"/bigobj",
		"/nologo",
		"/RTC1",
		"/RTCc",
		"/RTCs",
		"/RTCu",
		"/sdl",
		"/Wall",
		"/Wp64",
	}, cflags...)
	if *debug {
		line = append(line, "/Z7")			// keep debug information in the object file
	}
	line = append(line, "/Fo" + object)		// note: one parameter
	s := &Step{
		Name:	"Compiled " + filename,
		Line:		line,
	}
	stages = []Stage{
		Stage{s},
	}
	return stages, object
}

func (m *MSVC) BuildCFile(filename string, cflags []string) (stages []Stage, object string) {
	return m.buildRegularFile(
		"/TC",
		cflags,
		filename)
}

func (m *MSVC) BuildCXXFile(filename string, cflags []string) (stages []Stage, object string) {
	return m.buildRegularFile(
		"/TP",
		cflags,
		filename)
}

func (m *MSVC) BuildMFile(filename string, cflags []string) (stages []Stage, object string) {
	fail("Objective-C unimplemented on MSVC")
	panic("unreachable")
}

func (m *MSVC) BuildMMFile(filename string, cflags []string) (stages []Stage, object string) {
	fail("Objective-C++ unimplemented on MSVC")
	panic("unreachable")
}

func (m *MSVC) BuildRCFile(filename string, cflags []string) (stages []Stage, object string) {
	resfile := objectName(filename, ".res")
	object = objectName(filename, ".o")
	rcline := append([]string{
		"rc",
		// for rc, flags /must/ come first
		"/nologo",
		"/fo", resfile,		// note: two parameters
	}, cflags...)
	rcline = append(rcline, filename)
	s := &Step{
		Name:	"Created RES file from " + filename,
		Line:		rcline,
	}
	cvtline := append([]string{
		"cvtres",
		// for cvtres, flags /must/ come first
		"/nologo",
		"/out:" + object,	// note: one parameter
		resfile,
	}, cflags...)
	t := &Step{
		Name:	"Compiled object file from " + filename,
		Line:		cvtline,
	}
	stages = []Stage{
		Stage{s},
		Stage{t},
	}
	return stages, object
}

func (m *MSVC) Link(objects []string, ldflags []string, libs []string) *Step {
	target := targetName()
	for i := 0; i < len(libs); i++ {
		libs[i] = libs[i] + ".lib"
	}
	line := append([]string{
		"link",
		"/largeaddressaware",
		"/nologo",
	}, objects...)
	line = append(line, ldflags...)
	line = append(line, libs...)
	if *debug {
		// TODO MSDN claims it's not possible to have embedded debug symbols (apparently COFF doesn't exist)
	}
	line = append(line, "/OUT:" + target)			// note: one parameter
	return &Step{
		Name:	"Linked " + target,
		Line:		line,
	}
}

func (m *MSVC) Prepare() {
	// nothing to do here
}

func init() {
	toolchains["msvc"] = &MSVC{}
}
<commit_msg>More TODOs.<commit_after>// 27 september 2014

package main

import (
	// ...
)

type MSVC struct			{                                         }

// TODO /MDd, /MTd
// TODO /EHa?

func (m *MSVC) buildRegularFile(std string, cflags []string, filename string) (stages []Stage, object string) {
	object = objectName(filename, ".o")
	line := append([]string{
		"cl",
		filename,
		"/c",
		std,
		"/analyze",
		"/bigobj",
		"/nologo",
		"/RTC1",
		"/RTCc",
		"/RTCs",
		"/RTCu",
		"/sdl",
		"/Wall",
		"/Wp64",
	}, cflags...)
	if *debug {
		line = append(line, "/Z7")			// keep debug information in the object file
	}
	line = append(line, "/Fo" + object)		// note: one parameter
	s := &Step{
		Name:	"Compiled " + filename,
		Line:		line,
	}
	stages = []Stage{
		Stage{s},
	}
	return stages, object
}

func (m *MSVC) BuildCFile(filename string, cflags []string) (stages []Stage, object string) {
	return m.buildRegularFile(
		"/TC",
		cflags,
		filename)
}

func (m *MSVC) BuildCXXFile(filename string, cflags []string) (stages []Stage, object string) {
	return m.buildRegularFile(
		"/TP",
		cflags,
		filename)
}

func (m *MSVC) BuildMFile(filename string, cflags []string) (stages []Stage, object string) {
	fail("Objective-C unimplemented on MSVC")
	panic("unreachable")
}

func (m *MSVC) BuildMMFile(filename string, cflags []string) (stages []Stage, object string) {
	fail("Objective-C++ unimplemented on MSVC")
	panic("unreachable")
}

func (m *MSVC) BuildRCFile(filename string, cflags []string) (stages []Stage, object string) {
	resfile := objectName(filename, ".res")
	object = objectName(filename, ".o")
	rcline := append([]string{
		"rc",
		// for rc, flags /must/ come first
		"/nologo",
		"/fo", resfile,		// note: two parameters
	}, cflags...)
	rcline = append(rcline, filename)
	s := &Step{
		Name:	"Created RES file from " + filename,
		Line:		rcline,
	}
	cvtline := append([]string{
		"cvtres",
		// for cvtres, flags /must/ come first
		"/nologo",
		"/out:" + object,	// note: one parameter
		resfile,
	}, cflags...)
	t := &Step{
		Name:	"Compiled object file from " + filename,
		Line:		cvtline,
	}
	stages = []Stage{
		Stage{s},
		Stage{t},
	}
	return stages, object
}

func (m *MSVC) Link(objects []string, ldflags []string, libs []string) *Step {
	target := targetName()
	for i := 0; i < len(libs); i++ {
		libs[i] = libs[i] + ".lib"
	}
	line := append([]string{
		"link",
		"/largeaddressaware",
		"/nologo",
	}, objects...)
	line = append(line, ldflags...)
	line = append(line, libs...)
	if *debug {
		// TODO MSDN claims it's not possible to have embedded debug symbols (apparently COFF doesn't exist)
	}
	line = append(line, "/OUT:" + target)			// note: one parameter
	return &Step{
		Name:	"Linked " + target,
		Line:		line,
	}
}

func (m *MSVC) Prepare() {
	// nothing to do here
}

func init() {
	toolchains["msvc"] = &MSVC{}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/pkg/apis/core"
)

// ApplicationSpec defines the specification for an Application.
type ApplicationSpec struct {
	// Type is the type of the application (e.g. WordPress, MySQL, Cassandra).
	Type string `json:"type,omitempty"`

	// ComponentGroupKinds is a list of Kinds for Application's components (e.g. Deployments, Pods, Services, CRDs). It
	// can be used in conjunction with the Application's Selector to list or watch the Applications components.
	ComponentGroupKinds []metav1.GroupKind `json:"componentKinds,omitempty"`

	// Selector is a label query over kinds that created by the application. It must match the component objects' labels.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
	Selector *metav1.LabelSelector `json:"selector,omitempty"`

	// Version is an optional version indicator for the Application.
	Version string `json:"version,omitempty"`

	// Description is a brief string description of the Application.
	Description string `json:"description,omitempty"`

	// Maintainers is an optional list of maintainers of the application. The maintainers in this list maintain the
	// the source code, images, and package for the application.
	Maintainers []Maintainer `json:"maintainers,omitempty"`

	// Owners is an optional list of the owners of the installed application. The owners of the application should be
	// contacted in the event of a planned or unplanned disruption affecting the application.
	Owners []string `json:"owners,omitempty"`

	// Keywords is an optional list of key words associated with the application (e.g. MySQL, RDBMS, database).
	Keywords []string `json:"keywords,omitempty"`

	// Info contains human readable key,value pairs for the Application.
	Info []InfoItem `json:"info,omitempty"`

	// Links are a list of descriptive URLs intended to be used to surface additional documentation, dashboards, etc.
	Links []Link `json:"links,omitempty"`

	// Notes contain a human readable snippets intended as a quick start for the users of the Application.
	Notes string `json:"notes,omitempty"`

	// AssemblyPhase represents the current phase of the application's assembly.
	// An empty value is equivalent to "Succeeded".
	AssemblyPhase ApplicationAssemblyPhase `json:"assemblyPhase,omitempty"`
}

// ApplicationStatus defines controllers the observed state of Application
type ApplicationStatus struct {
	// ObservedGeneration is used by the Application Controller to report the last Generation of an Application
	// that it has observed.
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

// Maintainer contains information about an individual or organization that maintains the source code, images, and
// package for an Application. An Application can have more than one maintainer.
type Maintainer struct {
	// Name is the descriptive name of the maintainer.
	Name string `json:"name,omitempty"`

	// Url could typically be a website address.
	Url string `json:"url,omitempty"`

	// Email is the email address.
	Email string `json:"email,omitempty"`
}

// Link contains information about an URL to surface documentation, dashboards, etc.
type Link struct {
	// Description is human readable content explaining the purpose of the link.
	Description string `json:"description,omitempty"`

	// Url typically points at a website address.
	Url string `json:"url,omitempty"`
}

// InfoItem is a human readable key,value pair containing important information about how to access the Application.
type InfoItem struct {
	// Name is a human readable title for this piece of information.
	Name string `json:"name,omitempty"`

	// Value is human readable content.
	Value string `json:"value,omitempty"`

	// Value is derived from another source.
	ValueFrom *InfoItemSource `json:"valueFrom,omitempty"`
}

// InfoItemSource represents a source for the value of an InfoItem.
type InfoItemSource struct {
	// Selects a key of a Secret.
	SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty"`
	// Selects a key of a ConfigMap.
	ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
	// Select a Service.
	ServiceRef *ServiceSelector `json:"serviceRef,omitempty"`
	// Select an Ingress.
	IngressRef *IngressSelector `json:"ingressRef,omitempty"`
}

// ConfigMapKeySelector selects a key from a ConfigMap.
type ConfigMapKeySelector struct {
	// The ConfigMap to select from.
	core.ObjectReference
	// The key to select.
	Key string
}

// SecretKeySelector selects a key from a Secret.
type SecretKeySelector struct {
	// The Secrete to select from.
	core.ObjectReference
	// The key to select.
	Key string
}

// ServiceSelector selects a Service.
type ServiceSelector struct {
	// The Service to select from.
	core.ObjectReference `json:",inline"`
	// The optional port to select.
	Port *int32 `json:"port,omitempty"`
	// The optional HTTP path.
	Path string `json:"path,omitempty"`
}

// IngressSelector selects an Ingress.
type IngressSelector struct {
	// The Ingress to select from.
	core.ObjectReference `json:",inline"`
	// The optional host to select.
	Host string `json:"host,omitempty"`
	// The optional HTTP path.
	Path string `json:"path,omitempty"`
}

type ApplicationAssemblyPhase string

const (
	// Used to indicate that not all of application's components
	// have been deployed yet.
	Pending ApplicationAssemblyPhase = "Pending"
	// Used to indicate that all of application's components
	// have already been deployed.
	Succeeded = "Succeeded"
	// Used to indicate that deployment of application's components
	// failed. Some components might be present, but deployment of
	// the remaining ones will not be re-attempted.
	Failed = "Failed"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Application
// +k8s:openapi-gen=true
// +resource:path=applications
// The Application object acts as an aggregator for components that comprise an Application. Its
// Spec.ComponentGroupKinds indicate the GroupKinds of the components the comprise the Application. Its Spec. Selector
// is used to list and watch those components. All components of an Application should be labeled such the Application's
// Spec. Selector matches.
type Application struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
	// The specification object for the Application.
	Spec ApplicationSpec `json:"spec,omitempty"`
	// The status object for the Application.
	Status ApplicationStatus `json:"status,omitempty"`
}
<commit_msg>Fix a typo<commit_after>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/pkg/apis/core"
)

// ApplicationSpec defines the specification for an Application.
type ApplicationSpec struct {
	// Type is the type of the application (e.g. WordPress, MySQL, Cassandra).
	Type string `json:"type,omitempty"`

	// ComponentGroupKinds is a list of Kinds for Application's components (e.g. Deployments, Pods, Services, CRDs). It
	// can be used in conjunction with the Application's Selector to list or watch the Applications components.
	ComponentGroupKinds []metav1.GroupKind `json:"componentKinds,omitempty"`

	// Selector is a label query over kinds that created by the application. It must match the component objects' labels.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
	Selector *metav1.LabelSelector `json:"selector,omitempty"`

	// Version is an optional version indicator for the Application.
	Version string `json:"version,omitempty"`

	// Description is a brief string description of the Application.
	Description string `json:"description,omitempty"`

	// Maintainers is an optional list of maintainers of the application. The maintainers in this list maintain the
	// the source code, images, and package for the application.
	Maintainers []Maintainer `json:"maintainers,omitempty"`

	// Owners is an optional list of the owners of the installed application. The owners of the application should be
	// contacted in the event of a planned or unplanned disruption affecting the application.
	Owners []string `json:"owners,omitempty"`

	// Keywords is an optional list of key words associated with the application (e.g. MySQL, RDBMS, database).
	Keywords []string `json:"keywords,omitempty"`

	// Info contains human readable key,value pairs for the Application.
	Info []InfoItem `json:"info,omitempty"`

	// Links are a list of descriptive URLs intended to be used to surface additional documentation, dashboards, etc.
	Links []Link `json:"links,omitempty"`

	// Notes contain a human readable snippets intended as a quick start for the users of the Application.
	Notes string `json:"notes,omitempty"`

	// AssemblyPhase represents the current phase of the application's assembly.
	// An empty value is equivalent to "Succeeded".
	AssemblyPhase ApplicationAssemblyPhase `json:"assemblyPhase,omitempty"`
}

// ApplicationStatus defines controllers the observed state of Application
type ApplicationStatus struct {
	// ObservedGeneration is used by the Application Controller to report the last Generation of an Application
	// that it has observed.
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

// Maintainer contains information about an individual or organization that maintains the source code, images, and
// package for an Application. An Application can have more than one maintainer.
type Maintainer struct {
	// Name is the descriptive name of the maintainer.
	Name string `json:"name,omitempty"`

	// Url could typically be a website address.
	Url string `json:"url,omitempty"`

	// Email is the email address.
	Email string `json:"email,omitempty"`
}

// Link contains information about an URL to surface documentation, dashboards, etc.
type Link struct {
	// Description is human readable content explaining the purpose of the link.
	Description string `json:"description,omitempty"`

	// Url typically points at a website address.
	Url string `json:"url,omitempty"`
}

// InfoItem is a human readable key,value pair containing important information about how to access the Application.
type InfoItem struct {
	// Name is a human readable title for this piece of information.
	Name string `json:"name,omitempty"`

	// Value is human readable content.
	Value string `json:"value,omitempty"`

	// Value is derived from another source.
	ValueFrom *InfoItemSource `json:"valueFrom,omitempty"`
}

// InfoItemSource represents a source for the value of an InfoItem.
type InfoItemSource struct {
	// Selects a key of a Secret.
	SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty"`
	// Selects a key of a ConfigMap.
	ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
	// Select a Service.
	ServiceRef *ServiceSelector `json:"serviceRef,omitempty"`
	// Select an Ingress.
	IngressRef *IngressSelector `json:"ingressRef,omitempty"`
}

// ConfigMapKeySelector selects a key from a ConfigMap.
type ConfigMapKeySelector struct {
	// The ConfigMap to select from.
	core.ObjectReference
	// The key to select.
	Key string
}

// SecretKeySelector selects a key from a Secret.
type SecretKeySelector struct {
	// The Secret to select from.
	core.ObjectReference
	// The key to select.
	Key string
}

// ServiceSelector selects a Service.
type ServiceSelector struct {
	// The Service to select from.
	core.ObjectReference `json:",inline"`
	// The optional port to select.
	Port *int32 `json:"port,omitempty"`
	// The optional HTTP path.
	Path string `json:"path,omitempty"`
}

// IngressSelector selects an Ingress.
type IngressSelector struct {
	// The Ingress to select from.
	core.ObjectReference `json:",inline"`
	// The optional host to select.
	Host string `json:"host,omitempty"`
	// The optional HTTP path.
	Path string `json:"path,omitempty"`
}

type ApplicationAssemblyPhase string

const (
	// Used to indicate that not all of application's components
	// have been deployed yet.
	Pending ApplicationAssemblyPhase = "Pending"
	// Used to indicate that all of application's components
	// have already been deployed.
	Succeeded = "Succeeded"
	// Used to indicate that deployment of application's components
	// failed. Some components might be present, but deployment of
	// the remaining ones will not be re-attempted.
	Failed = "Failed"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Application
// +k8s:openapi-gen=true
// +resource:path=applications
// The Application object acts as an aggregator for components that comprise an Application. Its
// Spec.ComponentGroupKinds indicate the GroupKinds of the components the comprise the Application. Its Spec. Selector
// is used to list and watch those components. All components of an Application should be labeled such the Application's
// Spec. Selector matches.
type Application struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
	// The specification object for the Application.
	Spec ApplicationSpec `json:"spec,omitempty"`
	// The status object for the Application.
	Status ApplicationStatus `json:"status,omitempty"`
}
<|endoftext|>