<commit_before>package blog

import (
	"strconv"
	"strings"
	"time"
)

type Post struct {
	Id      int
	Title   string
	Author  string
	Body    string
	Written time.Time
}

// Unsafely parsing the time
func unsafeParseTime(input string) time.Time {
	t, e := time.Parse(input, input)
	if e != nil {
		panic(e)
	}
	return t
}

// Creating a new time-traveled post
func NewPostWithTime(id int, title string, author string, body string, written time.Time) *Post {
	post := new(Post)

	post.Id = id
	post.Title = title
	post.Author = author
	post.Body = body
	post.Written = written

	return post
}

// Creating a new Post
func NewPost(id int, title string, author string, body string) *Post {
	return NewPostWithTime(id, title, author, body, time.Now())
}

// Parsing out a Post
func ParsePost(input string) *Post {
	lines := strings.Split(input, "\n")

	id := 0
	title := ""
	author := ""
	body := ""
	written := time.Now()

	for index := 0; index < len(lines); index++ {
		liness := strings.SplitN(lines[index], " ", 2)

		if len(liness) == 2 {
			switch liness[0] {
			case "id":
				tid, err := strconv.ParseInt(liness[1], 10, 64)
				if err == nil {
					id = int(tid)
				}
			case "tit":
				title = liness[1]
			case "aut":
				author = liness[1]
			case "bod":
				body = liness[1]
			case "wri":
				twritten, err := time.Parse(liness[1], liness[1])
				if err == nil {
					written = twritten
				}
			}
		}
	}

	return NewPostWithTime(id, title, author, body, written)
}

// Showing a Post (converting it to a string)
func (post *Post) Show() string {
	return "id" + " " + strconv.FormatInt(int64(post.Id), 10) + "\n" +
		"tit" + " " + post.Title + "\n" +
		"aut" + " " + post.Author + "\n" +
		"bod" + " " + ParseMarkdown(post.Body) + "\n" +
		"wri" + " " + post.Written.String()
}
<commit_msg>Changed Post.Show() to Post.String() to be more idiomatic<commit_after>package blog

import (
	"strconv"
	"strings"
	"time"
)

type Post struct {
	Id      int
	Title   string
	Author  string
	Body    string
	Written time.Time
}

// Unsafely parsing the time
func unsafeParseTime(input string) time.Time {
	t, e := time.Parse(input, input)
	if e != nil {
		panic(e)
	}
	return t
}

// Creating a new time-traveled post
func NewPostWithTime(id int, title string, author string, body string, written time.Time) *Post {
	post := new(Post)

	post.Id = id
	post.Title = title
	post.Author = author
	post.Body = body
	post.Written = written

	return post
}

// Creating a new Post
func NewPost(id int, title string, author string, body string) *Post {
	return NewPostWithTime(id, title, author, body, time.Now())
}

// Parsing out a Post
func ParsePost(input string) *Post {
	lines := strings.Split(input, "\n")

	id := 0
	title := ""
	author := ""
	body := ""
	written := time.Now()

	for index := 0; index < len(lines); index++ {
		liness := strings.SplitN(lines[index], " ", 2)

		if len(liness) == 2 {
			switch liness[0] {
			case "id":
				tid, err := strconv.ParseInt(liness[1], 10, 64)
				if err == nil {
					id = int(tid)
				}
			case "tit":
				title = liness[1]
			case "aut":
				author = liness[1]
			case "bod":
				body = liness[1]
			case "wri":
				twritten, err := time.Parse(liness[1], liness[1])
				if err == nil {
					written = twritten
				}
			}
		}
	}

	return NewPostWithTime(id, title, author, body, written)
}

// Showing a Post (converting it to a string)
func (post *Post) String() string {
	return "id" + " " + strconv.FormatInt(int64(post.Id), 10) + "\n" +
		"tit" + " " + post.Title + "\n" +
		"aut" + " " + post.Author + "\n" +
		"bod" + " " + ParseMarkdown(post.Body) + "\n" +
		"wri" + " " + post.Written.String()
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package fdroidcl

import (
	"encoding/xml"
	"fmt"
	"io"
	"sort"
	"strings"

	"github.com/mvdan/adb"
)

type Index struct {
	Repo Repo  `xml:"repo"`
	Apps []App `xml:"application"`
}

type Repo struct {
	Name        string `xml:"name,attr"`
	PubKey      string `xml:"pubkey,attr"`
	Timestamp   int    `xml:"timestamp,attr"`
	URL         string `xml:"url,attr"`
	Version     int    `xml:"version,attr"`
	MaxAge      int    `xml:"maxage,attr"`
	Description string `xml:"description"`
}

// App is an Android application
type App struct {
	ID        string    `xml:"id"`
	Name      string    `xml:"name"`
	Summary   string    `xml:"summary"`
	Added     DateVal   `xml:"added"`
	Updated   DateVal   `xml:"lastupdated"`
	Icon      string    `xml:"icon"`
	Desc      string    `xml:"desc"`
	License   string    `xml:"license"`
	Categs    CommaList `xml:"categories"`
	Website   string    `xml:"web"`
	Source    string    `xml:"source"`
	Tracker   string    `xml:"tracker"`
	Changelog string    `xml:"changelog"`
	Donate    string    `xml:"donate"`
	Bitcoin   string    `xml:"bitcoin"`
	Litecoin  string    `xml:"litecoin"`
	FlattrID  string    `xml:"flattr"`
	Apks      []Apk     `xml:"package"`
	CVName    string    `xml:"marketversion"`
	CVCode    int       `xml:"marketvercode"`
}

type IconDensity uint

const (
	UnknownDensity IconDensity = 0
	LowDensity     IconDensity = 120
	MediumDensity  IconDensity = 160
	HighDensity    IconDensity = 240
	XHighDensity   IconDensity = 320
	XXHighDensity  IconDensity = 480
	XXXHighDensity IconDensity = 640
)

func getIconsDir(density IconDensity) string {
	if density == UnknownDensity {
		return "icons"
	}
	for _, d := range [...]IconDensity{
		XXXHighDensity,
		XXHighDensity,
		XHighDensity,
		HighDensity,
		MediumDensity,
	} {
		if density >= d {
			return fmt.Sprintf("icons-%d", d)
		}
	}
	return fmt.Sprintf("icons-%d", LowDensity)
}

func (a *App) IconURLForDensity(density IconDensity) string {
	cur := a.CurApk()
	if cur == nil {
		return ""
	}
	return fmt.Sprintf("%s/%s/%s", cur.Repo.URL, getIconsDir(density), a.Icon)
}

func (a *App) IconURL() string {
	return a.IconURLForDensity(UnknownDensity)
}

func (a *App) TextDesc(w io.Writer) {
	reader := strings.NewReader(a.Desc)
	decoder := xml.NewDecoder(reader)
	firstParagraph := true
	linePrefix := ""
	colsUsed := 0
	var links []string
	linked := false
	for {
		token, err := decoder.Token()
		if err == io.EOF || token == nil {
			break
		}
		switch t := token.(type) {
		case xml.StartElement:
			switch t.Name.Local {
			case "p":
				if firstParagraph {
					firstParagraph = false
				} else {
					fmt.Fprintln(w)
				}
				linePrefix = ""
				colsUsed = 0
			case "li":
				fmt.Fprint(w, "\n *")
				linePrefix = "   "
				colsUsed = 0
			case "a":
				for _, attr := range t.Attr {
					if attr.Name.Local == "href" {
						links = append(links, attr.Value)
						linked = true
						break
					}
				}
			}
		case xml.EndElement:
			switch t.Name.Local {
			case "p":
				fmt.Fprintln(w)
			case "ul":
				fmt.Fprintln(w)
			case "ol":
				fmt.Fprintln(w)
			}
		case xml.CharData:
			left := string(t)
			if linked {
				left += fmt.Sprintf("[%d]", len(links)-1)
				linked = false
			}
			limit := 80 - len(linePrefix) - colsUsed
			firstLine := true
			for len(left) > limit {
				last := 0
				for i, c := range left {
					if i >= limit {
						break
					}
					if c == ' ' {
						last = i
					}
				}
				if firstLine {
					firstLine = false
					limit += colsUsed
				} else {
					fmt.Fprint(w, linePrefix)
				}
				fmt.Fprintln(w, left[:last])
				left = left[last+1:]
				colsUsed = 0
			}
			if !firstLine {
				fmt.Fprint(w, linePrefix)
			}
			fmt.Fprint(w, left)
			colsUsed += len(left)
		}
	}
	if len(links) > 0 {
		fmt.Fprintln(w)
		for i, link := range links {
			fmt.Fprintf(w, "[%d] %s\n", i, link)
		}
	}
}

// Apk is an Android package
type Apk struct {
	VName   string    `xml:"version"`
	VCode   int       `xml:"versioncode"`
	Size    int64     `xml:"size"`
	MinSdk  int       `xml:"sdkver"`
	MaxSdk  int       `xml:"maxsdkver"`
	ABIs    CommaList `xml:"nativecode"`
	ApkName string    `xml:"apkname"`
	SrcName string    `xml:"srcname"`
	Sig     HexVal    `xml:"sig"`
	Added   DateVal   `xml:"added"`
	Perms   CommaList `xml:"permissions"`
	Feats   CommaList `xml:"features"`
	Hash    HexHash   `xml:"hash"`

	App  *App  `xml:"-"`
	Repo *Repo `xml:"-"`
}

func (a *Apk) URL() string {
	return fmt.Sprintf("%s/%s", a.Repo.URL, a.ApkName)
}

func (a *Apk) SrcURL() string {
	return fmt.Sprintf("%s/%s", a.Repo.URL, a.SrcName)
}

func (apk *Apk) IsCompatibleABI(ABIs []string) bool {
	if len(apk.ABIs) == 0 {
		return true // APK does not contain native code
	}
	for i := range apk.ABIs {
		for j := range ABIs {
			if apk.ABIs[i] == ABIs[j] {
				return true
			}
		}
	}
	return false
}

func (apk *Apk) IsCompatibleAPILevel(sdk int) bool {
	return sdk >= apk.MinSdk && (apk.MaxSdk == 0 || sdk <= apk.MaxSdk)
}

func (apk *Apk) IsCompatible(device *adb.Device) bool {
	return apk.IsCompatibleABI(device.ABIs) &&
		apk.IsCompatibleAPILevel(device.APILevel)
}

type AppList []App

func (al AppList) Len() int           { return len(al) }
func (al AppList) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al AppList) Less(i, j int) bool { return al[i].ID < al[j].ID }

type ApkList []Apk

func (al ApkList) Len() int           { return len(al) }
func (al ApkList) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al ApkList) Less(i, j int) bool { return al[i].VCode > al[j].VCode }

func LoadIndexXML(r io.Reader) (*Index, error) {
	var index Index
	decoder := xml.NewDecoder(r)
	if err := decoder.Decode(&index); err != nil {
		return nil, err
	}

	sort.Sort(AppList(index.Apps))

	for i := range index.Apps {
		app := &index.Apps[i]
		sort.Sort(ApkList(app.Apks))
		for j := range app.Apks {
			apk := &app.Apks[j]
			apk.App = app
			apk.Repo = &index.Repo
		}
	}
	return &index, nil
}

func (a *App) CurApk() *Apk {
	for i := range a.Apks {
		apk := a.Apks[i]
		if a.CVCode >= apk.VCode {
			return &apk
		}
	}
	if len(a.Apks) > 0 {
		return &a.Apks[0]
	}
	return nil
}

func (a *App) ApksByVName(vname string) []Apk {
	var apks []Apk
	for i := range a.Apks {
		if vname == a.Apks[i].VName {
			apks = append(apks, a.Apks[i])
		}
	}
	return apks
}

func (a *App) SuggestedVName() string {
	for i := range a.Apks {
		apk := &a.Apks[i]
		if a.CVCode >= apk.VCode {
			return apk.VName
		}
	}
	return ""
}

func (a *App) SuggestedApks() []Apk {
	// No APKs => nothing to suggest
	if len(a.Apks) == 0 {
		return nil
	}

	// First, try to follow CV
	apks := a.ApksByVName(a.SuggestedVName())
	if len(apks) > 0 {
		return apks
	}

	// When CV is missing current version code or it's invalid (no APKs
	// match it), use heuristic: find all APKs having the same version
	// string as the APK with the greatest version code
	return a.ApksByVName(a.Apks[0].VName)
}

func (a *App) SuggestedApk(device *adb.Device) *Apk {
	for i := range a.Apks {
		apk := &a.Apks[i]
		if a.CVCode >= apk.VCode && apk.IsCompatible(device) {
			return apk
		}
	}
	for i := range a.Apks {
		apk := &a.Apks[i]
		if apk.IsCompatible(device) {
			return apk
		}
	}
	return nil
}
<commit_msg>Pick app icon from the latest APK<commit_after>// Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package fdroidcl

import (
	"encoding/xml"
	"fmt"
	"io"
	"sort"
	"strings"

	"github.com/mvdan/adb"
)

type Index struct {
	Repo Repo  `xml:"repo"`
	Apps []App `xml:"application"`
}

type Repo struct {
	Name        string `xml:"name,attr"`
	PubKey      string `xml:"pubkey,attr"`
	Timestamp   int    `xml:"timestamp,attr"`
	URL         string `xml:"url,attr"`
	Version     int    `xml:"version,attr"`
	MaxAge      int    `xml:"maxage,attr"`
	Description string `xml:"description"`
}

// App is an Android application
type App struct {
	ID        string    `xml:"id"`
	Name      string    `xml:"name"`
	Summary   string    `xml:"summary"`
	Added     DateVal   `xml:"added"`
	Updated   DateVal   `xml:"lastupdated"`
	Icon      string    `xml:"icon"`
	Desc      string    `xml:"desc"`
	License   string    `xml:"license"`
	Categs    CommaList `xml:"categories"`
	Website   string    `xml:"web"`
	Source    string    `xml:"source"`
	Tracker   string    `xml:"tracker"`
	Changelog string    `xml:"changelog"`
	Donate    string    `xml:"donate"`
	Bitcoin   string    `xml:"bitcoin"`
	Litecoin  string    `xml:"litecoin"`
	FlattrID  string    `xml:"flattr"`
	Apks      []Apk     `xml:"package"`
	CVName    string    `xml:"marketversion"`
	CVCode    int       `xml:"marketvercode"`
}

type IconDensity uint

const (
	UnknownDensity IconDensity = 0
	LowDensity     IconDensity = 120
	MediumDensity  IconDensity = 160
	HighDensity    IconDensity = 240
	XHighDensity   IconDensity = 320
	XXHighDensity  IconDensity = 480
	XXXHighDensity IconDensity = 640
)

func getIconsDir(density IconDensity) string {
	if density == UnknownDensity {
		return "icons"
	}
	for _, d := range [...]IconDensity{
		XXXHighDensity,
		XXHighDensity,
		XHighDensity,
		HighDensity,
		MediumDensity,
	} {
		if density >= d {
			return fmt.Sprintf("icons-%d", d)
		}
	}
	return fmt.Sprintf("icons-%d", LowDensity)
}

func (a *App) IconURLForDensity(density IconDensity) string {
	if len(a.Apks) == 0 {
		return ""
	}
	return fmt.Sprintf("%s/%s/%s", a.Apks[0].Repo.URL,
		getIconsDir(density), a.Icon)
}

func (a *App) IconURL() string {
	return a.IconURLForDensity(UnknownDensity)
}

func (a *App) TextDesc(w io.Writer) {
	reader := strings.NewReader(a.Desc)
	decoder := xml.NewDecoder(reader)
	firstParagraph := true
	linePrefix := ""
	colsUsed := 0
	var links []string
	linked := false
	for {
		token, err := decoder.Token()
		if err == io.EOF || token == nil {
			break
		}
		switch t := token.(type) {
		case xml.StartElement:
			switch t.Name.Local {
			case "p":
				if firstParagraph {
					firstParagraph = false
				} else {
					fmt.Fprintln(w)
				}
				linePrefix = ""
				colsUsed = 0
			case "li":
				fmt.Fprint(w, "\n *")
				linePrefix = "   "
				colsUsed = 0
			case "a":
				for _, attr := range t.Attr {
					if attr.Name.Local == "href" {
						links = append(links, attr.Value)
						linked = true
						break
					}
				}
			}
		case xml.EndElement:
			switch t.Name.Local {
			case "p":
				fmt.Fprintln(w)
			case "ul":
				fmt.Fprintln(w)
			case "ol":
				fmt.Fprintln(w)
			}
		case xml.CharData:
			left := string(t)
			if linked {
				left += fmt.Sprintf("[%d]", len(links)-1)
				linked = false
			}
			limit := 80 - len(linePrefix) - colsUsed
			firstLine := true
			for len(left) > limit {
				last := 0
				for i, c := range left {
					if i >= limit {
						break
					}
					if c == ' ' {
						last = i
					}
				}
				if firstLine {
					firstLine = false
					limit += colsUsed
				} else {
					fmt.Fprint(w, linePrefix)
				}
				fmt.Fprintln(w, left[:last])
				left = left[last+1:]
				colsUsed = 0
			}
			if !firstLine {
				fmt.Fprint(w, linePrefix)
			}
			fmt.Fprint(w, left)
			colsUsed += len(left)
		}
	}
	if len(links) > 0 {
		fmt.Fprintln(w)
		for i, link := range links {
			fmt.Fprintf(w, "[%d] %s\n", i, link)
		}
	}
}

// Apk is an Android package
type Apk struct {
	VName   string    `xml:"version"`
	VCode   int       `xml:"versioncode"`
	Size    int64     `xml:"size"`
	MinSdk  int       `xml:"sdkver"`
	MaxSdk  int       `xml:"maxsdkver"`
	ABIs    CommaList `xml:"nativecode"`
	ApkName string    `xml:"apkname"`
	SrcName string    `xml:"srcname"`
	Sig     HexVal    `xml:"sig"`
	Added   DateVal   `xml:"added"`
	Perms   CommaList `xml:"permissions"`
	Feats   CommaList `xml:"features"`
	Hash    HexHash   `xml:"hash"`

	App  *App  `xml:"-"`
	Repo *Repo `xml:"-"`
}

func (a *Apk) URL() string {
	return fmt.Sprintf("%s/%s", a.Repo.URL, a.ApkName)
}

func (a *Apk) SrcURL() string {
	return fmt.Sprintf("%s/%s", a.Repo.URL, a.SrcName)
}

func (apk *Apk) IsCompatibleABI(ABIs []string) bool {
	if len(apk.ABIs) == 0 {
		return true // APK does not contain native code
	}
	for i := range apk.ABIs {
		for j := range ABIs {
			if apk.ABIs[i] == ABIs[j] {
				return true
			}
		}
	}
	return false
}

func (apk *Apk) IsCompatibleAPILevel(sdk int) bool {
	return sdk >= apk.MinSdk && (apk.MaxSdk == 0 || sdk <= apk.MaxSdk)
}

func (apk *Apk) IsCompatible(device *adb.Device) bool {
	return apk.IsCompatibleABI(device.ABIs) &&
		apk.IsCompatibleAPILevel(device.APILevel)
}

type AppList []App

func (al AppList) Len() int           { return len(al) }
func (al AppList) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al AppList) Less(i, j int) bool { return al[i].ID < al[j].ID }

type ApkList []Apk

func (al ApkList) Len() int           { return len(al) }
func (al ApkList) Swap(i, j int)      { al[i], al[j] = al[j], al[i] }
func (al ApkList) Less(i, j int) bool { return al[i].VCode > al[j].VCode }

func LoadIndexXML(r io.Reader) (*Index, error) {
	var index Index
	decoder := xml.NewDecoder(r)
	if err := decoder.Decode(&index); err != nil {
		return nil, err
	}

	sort.Sort(AppList(index.Apps))

	for i := range index.Apps {
		app := &index.Apps[i]
		sort.Sort(ApkList(app.Apks))
		for j := range app.Apks {
			apk := &app.Apks[j]
			apk.App = app
			apk.Repo = &index.Repo
		}
	}
	return &index, nil
}

func (a *App) CurApk() *Apk {
	for i := range a.Apks {
		apk := a.Apks[i]
		if a.CVCode >= apk.VCode {
			return &apk
		}
	}
	if len(a.Apks) > 0 {
		return &a.Apks[0]
	}
	return nil
}

func (a *App) ApksByVName(vname string) []Apk {
	var apks []Apk
	for i := range a.Apks {
		if vname == a.Apks[i].VName {
			apks = append(apks, a.Apks[i])
		}
	}
	return apks
}

func (a *App) SuggestedVName() string {
	for i := range a.Apks {
		apk := &a.Apks[i]
		if a.CVCode >= apk.VCode {
			return apk.VName
		}
	}
	return ""
}

func (a *App) SuggestedApks() []Apk {
	// No APKs => nothing to suggest
	if len(a.Apks) == 0 {
		return nil
	}

	// First, try to follow CV
	apks := a.ApksByVName(a.SuggestedVName())
	if len(apks) > 0 {
		return apks
	}

	// When CV is missing current version code or it's invalid (no APKs
	// match it), use heuristic: find all APKs having the same version
	// string as the APK with the greatest version code
	return a.ApksByVName(a.Apks[0].VName)
}

func (a *App) SuggestedApk(device *adb.Device) *Apk {
	for i := range a.Apks {
		apk := &a.Apks[i]
		if a.CVCode >= apk.VCode && apk.IsCompatible(device) {
			return apk
		}
	}
	for i := range a.Apks {
		apk := &a.Apks[i]
		if apk.IsCompatible(device) {
			return apk
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package bsw

import (
	"errors"
	"github.com/miekg/dns"
)

// Search for a possible wild card host by attempting to
// get an A record youmustconstructmoreplylong.[domain].
func GetWildCard(domain, serverAddr string) string {
	var fqdn = "youmustconstructmorepylons." + domain
	m := &dns.Msg{}
	m.SetQuestion(dns.Fqdn(fqdn), dns.TypeA)
	in, err := dns.Exchange(m, serverAddr+":53")
	if err != nil {
		return ""
	}
	if len(in.Answer) < 1 {
		return ""
	}
	if a, ok := in.Answer[0].(*dns.A); ok {
		return a.A.String()
	} else {
		return ""
	}
}

// Search for a possible wild card host by attempting to
// get an AAAA record youmustconstructmoreplylong.[domain].
func GetWildCard6(domain, serverAddr string) string {
	var fqdn = "youmustconstructmorepylons." + domain
	m := &dns.Msg{}
	m.SetQuestion(dns.Fqdn(fqdn), dns.TypeAAAA)
	in, err := dns.Exchange(m, serverAddr+":53")
	if err != nil {
		return ""
	}
	if len(in.Answer) < 1 {
		return ""
	}
	if a, ok := in.Answer[0].(*dns.AAAA); ok {
		return a.AAAA.String()
	} else {
		return ""
	}
}

// Attempt to get an A and CNAME record for a sub domain of domain.
func Dictionary(domain, subname, blacklist, serverAddr string) (Results, error) {
	results := Results{}
	var fqdn = subname + "." + domain
	ip, err := LookupName(fqdn, serverAddr)
	if err != nil {
		cfqdn, err := LookupCname(fqdn, serverAddr)
		if err != nil {
			return results, err
		}
		ip, err = LookupName(cfqdn, serverAddr)
		if err != nil {
			return results, err
		}
		if ip == blacklist {
			return results, errors.New("Returned IP in blackslist")
		}
		results = append(results, Result{Source: "Dictionary-CNAME", IP: ip, Hostname: fqdn}, Result{Source: "Dictionary-CNAME", IP: ip, Hostname: cfqdn})
		return results, nil
	}
	if ip == blacklist {
		return results, errors.New("Returned IP in blacklist")
	}
	results = append(results, Result{Source: "Dictionary", IP: ip, Hostname: fqdn})
	return results, nil
}

// Attempt to get an AAAA record for a sub domain of a domain.
func Dictionary6(domain, subname, blacklist, serverAddr string) (Results, error) {
	results := Results{}
	var fqdn = subname + "." + domain
	ip, err := LookupName6(fqdn, serverAddr)
	if err != nil {
		return results, err
	}
	if ip == blacklist {
		return results, errors.New("Returned IP in blacklist")
	}
	results = append(results, Result{Source: "Dictionary IPv6", IP: ip, Hostname: fqdn})
	return results, nil
}
<commit_msg>Fix slight typo<commit_after>package bsw

import (
	"errors"
	"github.com/miekg/dns"
)

// Search for a possible wild card host by attempting to
// get an A record youmustconstructmoreplylons.[domain].
func GetWildCard(domain, serverAddr string) string {
	var fqdn = "youmustconstructmorepylons." + domain
	m := &dns.Msg{}
	m.SetQuestion(dns.Fqdn(fqdn), dns.TypeA)
	in, err := dns.Exchange(m, serverAddr+":53")
	if err != nil {
		return ""
	}
	if len(in.Answer) < 1 {
		return ""
	}
	if a, ok := in.Answer[0].(*dns.A); ok {
		return a.A.String()
	} else {
		return ""
	}
}

// Search for a possible wild card host by attempting to
// get an AAAA record youmustconstructmoreplylons.[domain].
func GetWildCard6(domain, serverAddr string) string {
	var fqdn = "youmustconstructmorepylons." + domain
	m := &dns.Msg{}
	m.SetQuestion(dns.Fqdn(fqdn), dns.TypeAAAA)
	in, err := dns.Exchange(m, serverAddr+":53")
	if err != nil {
		return ""
	}
	if len(in.Answer) < 1 {
		return ""
	}
	if a, ok := in.Answer[0].(*dns.AAAA); ok {
		return a.AAAA.String()
	} else {
		return ""
	}
}

// Attempt to get an A and CNAME record for a sub domain of domain.
func Dictionary(domain, subname, blacklist, serverAddr string) (Results, error) {
	results := Results{}
	var fqdn = subname + "." + domain
	ip, err := LookupName(fqdn, serverAddr)
	if err != nil {
		cfqdn, err := LookupCname(fqdn, serverAddr)
		if err != nil {
			return results, err
		}
		ip, err = LookupName(cfqdn, serverAddr)
		if err != nil {
			return results, err
		}
		if ip == blacklist {
			return results, errors.New("Returned IP in blackslist")
		}
		results = append(results, Result{Source: "Dictionary-CNAME", IP: ip, Hostname: fqdn}, Result{Source: "Dictionary-CNAME", IP: ip, Hostname: cfqdn})
		return results, nil
	}
	if ip == blacklist {
		return results, errors.New("Returned IP in blacklist")
	}
	results = append(results, Result{Source: "Dictionary", IP: ip, Hostname: fqdn})
	return results, nil
}

// Attempt to get an AAAA record for a sub domain of a domain.
func Dictionary6(domain, subname, blacklist, serverAddr string) (Results, error) {
	results := Results{}
	var fqdn = subname + "." + domain
	ip, err := LookupName6(fqdn, serverAddr)
	if err != nil {
		return results, err
	}
	if ip == blacklist {
		return results, errors.New("Returned IP in blacklist")
	}
	results = append(results, Result{Source: "Dictionary IPv6", IP: ip, Hostname: fqdn})
	return results, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bitbucket.org/sinbad/git-lob/providers/smart"
	"bufio"
	"encoding/json"
	"fmt"
	"io"
)

type MethodFunc func(req *smart.JsonRequest, in io.Reader, out io.Writer, config *Config, path string) *smart.JsonResponse

var methodMap = map[string]MethodFunc{
	"QueryCaps":            queryCaps,
	"SetEnabledCaps":       setCaps,
	"FileExists":           fileExists,
	"FileExistsOfSize":     fileExistsOfSize,
	"UploadFile":           uploadFile,
	"DownloadFilePrepare":  downloadFilePrepare,
	"DownloadFileStart":    downloadFileStart,
	"PickCompleteLOB":      pickCompleteLOB,
	"UploadDelta":          uploadDelta,
	"DownloadDeltaPrepare": downloadDeltaPrepare,
	"DownloadDeltaStart":   downloadDeltaStart,
}

func Serve(in io.Reader, out io.Writer, outerr io.Writer, config *Config, path string) int {

	// Read input from client on stdin, buffered so we can detect terminators for JSON

	rdr := bufio.NewReader(in)
	// we keep reading until stdin is closed
	for {
		jsonbytes, err := rdr.ReadBytes(byte(0))
		if err != nil {
			if err == io.EOF {
				// normal exit
				break
			}
			fmt.Fprintf(outerr, "Unable to read from client: %v\n", err.Error())
			return 21
		}
		// slice off the terminator
		jsonbytes = jsonbytes[:len(jsonbytes)-1]
		var req smart.JsonRequest
		err = json.Unmarshal(jsonbytes, &req)
		if err != nil {
			fmt.Fprintf(outerr, "Unable to unmarhsal JSON: %v: %v\n", string(jsonbytes), err.Error())
			return 22
		}

		// Get function to handle method
		f, ok := methodMap[req.Method]
		var resp *smart.JsonResponse
		if !ok {
			// Since it was valid JSON otherwise, send error as response
			resp = smart.NewJsonErrorResponse(req.Id, fmt.Sprintf("Unknown method %v", req.Method))
		} else {
			// method found, process
			resp = f(&req, rdr, out, config, path)
		}
		// There may not have been a JSON response; that might be because method just streams bytes
		// in which case we just ignore this bit
		if resp != nil {
			err := sendResponse(resp, out)
			if err != nil {
				fmt.Fprintf(outerr, "%v\n", err.Error())
				return 23
			}
		}

		// Ready for next request from client

	}

	return 0
}

func sendResponse(resp *smart.JsonResponse, out io.Writer) error {
	responseBytes, err := json.Marshal(resp)
	if err != nil {
		return fmt.Errorf("Unable to marhsal JSON response: %v: %v", resp, err.Error())
	}
	// null terminate response
	responseBytes = append(responseBytes, byte(0))
	_, err = out.Write(responseBytes)
	return err
}
<commit_msg>For convenience, make Serve() turn standard error responses into stderr output in cases where only a byte stream response is allowed<commit_after>package main

import (
	"bitbucket.org/sinbad/git-lob/providers/smart"
	"bitbucket.org/sinbad/git-lob/util"
	"bufio"
	"encoding/json"
	"fmt"
	"io"
)

type MethodFunc func(req *smart.JsonRequest, in io.Reader, out io.Writer, config *Config, path string) *smart.JsonResponse

var methodMap = map[string]MethodFunc{
	"QueryCaps":            queryCaps,
	"SetEnabledCaps":       setCaps,
	"FileExists":           fileExists,
	"FileExistsOfSize":     fileExistsOfSize,
	"UploadFile":           uploadFile,
	"DownloadFilePrepare":  downloadFilePrepare,
	"DownloadFileStart":    downloadFileStart,
	"PickCompleteLOB":      pickCompleteLOB,
	"UploadDelta":          uploadDelta,
	"DownloadDeltaPrepare": downloadDeltaPrepare,
	"DownloadDeltaStart":   downloadDeltaStart,
}

// these methods can't return any error responses
var bytestreamResponseMethods = util.NewStringSetFromSlice([]string{
	"DownloadFileStart",
	"DownloadDeltaStart",
})

func Serve(in io.Reader, out io.Writer, outerr io.Writer, config *Config, path string) int {

	// Read input from client on stdin, buffered so we can detect terminators for JSON

	rdr := bufio.NewReader(in)
	// we keep reading until stdin is closed
	for {
		jsonbytes, err := rdr.ReadBytes(byte(0))
		if err != nil {
			if err == io.EOF {
				// normal exit
				break
			}
			fmt.Fprintf(outerr, "Unable to read from client: %v\n", err.Error())
			return 21
		}
		// slice off the terminator
		jsonbytes = jsonbytes[:len(jsonbytes)-1]
		var req smart.JsonRequest
		err = json.Unmarshal(jsonbytes, &req)
		if err != nil {
			fmt.Fprintf(outerr, "Unable to unmarhsal JSON: %v: %v\n", string(jsonbytes), err.Error())
			return 22
		}

		// Get function to handle method
		f, ok := methodMap[req.Method]
		var resp *smart.JsonResponse
		if !ok {
			// Since it was valid JSON otherwise, send error as response
			resp = smart.NewJsonErrorResponse(req.Id, fmt.Sprintf("Unknown method %v", req.Method))
		} else {
			// method found, process
			resp = f(&req, rdr, out, config, path)
		}
		// There may not have been a JSON response; that might be because method just streams bytes
		// in which case we just ignore this bit
		if resp != nil {
			if resp.Error != "" && bytestreamResponseMethods.Contains(req.Method) {
				// there was an error but this was a bytestream-only method so can't return JSON
				// just send it to stderr
				fmt.Fprintf(outerr, "%v\n", resp.Error)
				return 33
			} else {
				// normal method which responds in JSON
				err := sendResponse(resp, out)
				if err != nil {
					fmt.Fprintf(outerr, "%v\n", err.Error())
					return 23
				}
			}
		}

		// Ready for next request from client

	}

	return 0
}

func sendResponse(resp *smart.JsonResponse, out io.Writer) error {
	responseBytes, err := json.Marshal(resp)
	if err != nil {
		return fmt.Errorf("Unable to marhsal JSON response: %v: %v", resp, err.Error())
	}
	// null terminate response
	responseBytes = append(responseBytes, byte(0))
	_, err = out.Write(responseBytes)
	return err
}
<|endoftext|>


<commit_before>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	"github.com/eirka/eirka-libs/user"

	local "github.com/eirka/eirka-post/config"
)

func init() {

	// Database connection settings
	dbase := db.Database{

		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	config.GetDatabaseSettings()

	user.Secret = "secret"
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtJsonRequest(r http.Handler, method, path, token string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtFormRequest(r http.Handler, method, path, token string, body bytes.Buffer) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, &body)
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
	req.Header.Set("Content-Type", "multipart/form-data")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func TestEmailController(t *testing.T) {

	var err error

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	router.Use(user.Auth(true))

	router.POST("/email", EmailController)

	first := performRequest(router, "POST", "/email")

	assert.Equal(t, first.Code, 401, "HTTP request code should match")

	u := user.DefaultUser()
	u.SetId(2)
	u.SetAuthenticated()
	u.Password()

	assert.True(t, u.ComparePassword("testpassword"), "Test user password should be set")

	token, err := u.CreateToken()
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotEmpty(t, token, "token should be returned")
	}

	request1 := []byte(`{"ib": 1, "email": "test@test.com"}`)

	second := performJwtJsonRequest(router, "POST", "/email", token, request1)

	assert.Equal(t, second.Code, 200, "HTTP request code should match")
	assert.Equal(t, second.Body.String(), `{"success_message":"Email Updated"}`, "HTTP response should match")

	request2 := []byte(`{"ib": 1, "email": "test@test.com"}`)

	third := performJwtJsonRequest(router, "POST", "/email", token, request2)

	assert.Equal(t, third.Code, 400, "HTTP request code should match")
	assert.Equal(t, third.Body.String(), `{"error_message":"Email address the same"}`, "HTTP response should match")

	request3 := []byte(`{"ib": 1, "email": "test@cool.com"}`)

	fourth := performJwtJsonRequest(router, "POST", "/email", token, request3)

	assert.Equal(t, fourth.Code, 200, "HTTP request code should match")
	assert.Equal(t, fourth.Body.String(), `{"success_message":"Email Updated"}`, "HTTP response should match")

}
<commit_msg>add email test<commit_after>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	"github.com/eirka/eirka-libs/user"

	local "github.com/eirka/eirka-post/config"
)

func init() {

	// Database connection settings
	dbase := db.Database{

		User:           local.Settings.Database.User,
		Password:       local.Settings.Database.Password,
		Proto:          local.Settings.Database.Proto,
		Host:           local.Settings.Database.Host,
		Database:       local.Settings.Database.Database,
		MaxIdle:        local.Settings.Database.MaxIdle,
		MaxConnections: local.Settings.Database.MaxConnections,
	}

	// Set up DB connection
	dbase.NewDb()

	// Get limits and stuff from database
	config.GetDatabaseSettings()

	user.Secret = "secret"
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtJsonRequest(r http.Handler, method, path, token string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJwtFormRequest(r http.Handler, method, path, token string, body bytes.Buffer) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, &body)
	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
	req.Header.Set("Content-Type", "multipart/form-data")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func TestEmailController(t *testing.T) {

	var err error

	gin.SetMode(gin.ReleaseMode)

	router := gin.New()

	router.Use(user.Auth(true))

	router.POST("/email", EmailController)

	first := performRequest(router, "POST", "/email")

	assert.Equal(t, first.Code, 401, "HTTP request code should match")

	u := user.DefaultUser()
	u.SetId(2)
	u.SetAuthenticated()
	u.Password()

	assert.True(t, u.ComparePassword("testpassword"), "Test user password should be set")

	token, err := u.CreateToken()
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotEmpty(t, token, "token should be returned")
	}

	request1 := []byte(`{"ib": 1, "email": "test@test.com"}`)

	second := performJwtJsonRequest(router, "POST", "/email", token, request1)

	assert.Equal(t, second.Code, 200, "HTTP request code should match")
	assert.Equal(t, second.Body.Bytes(), []byte(`{"success_message":"Email Updated"}`), "HTTP response should match")

	request2 := []byte(`{"ib": 1, "email": "test@test.com"}`)

	third := performJwtJsonRequest(router, "POST", "/email", token, request2)

	assert.Equal(t, third.Code, 400, "HTTP request code should match")
	assert.Equal(t, third.Body.Bytes(), []byte(`{"error_message":"Email address the same"}`), "HTTP response should match")

	request3 := []byte(`{"ib": 1, "email": "test@cool.com"}`)

	fourth := performJwtJsonRequest(router, "POST", "/email", token, request3)

	assert.Equal(t, fourth.Code, 200, "HTTP request code should match")
	assert.Equal(t, fourth.Body.Bytes(), []byte(`{"success_message":"Email Updated"}`), "HTTP response should match")

}
<|endoftext|>


<commit_before>package consul

import (
	"encoding/json"
	"fmt"

	"sync"

	"github.com/Sirupsen/logrus"
	qgoutils "github.com/chennqqi/goutils/utils"
	"github.com/chennqqi/goutils/yamlconfig"
	consulapi "github.com/hashicorp/consul/api"
	"github.com/pkg/errors"
)

const (
	CONSUL_HEALTH_PATH = "health"
)

type ConsulOperator struct {
	Agent    string `json:"agent,omitempty" yaml:"agent,omitempty"`
	IP       string `json:"ip" yaml:"ip"`
	Port     int    `json:"port" yaml:"port"`
	Name     string `json:"Name" yaml:"Name"`
	Path     string `json:"path,omitempty" yaml:"path,omitempty"`
	Interval string `json:"interval,omitempty" yaml:"interval,omitempty"`

	//for check
	consul  *consulapi.Client `json:"-" yaml:"-"`
	once    sync.Once
	lockmap map[string]*consulapi.Lock
}

func NewConsulOp(agent string) *ConsulOperator {
	var c ConsulOperator
	c.lockmap = make(map[string]*consulapi.Lock)
	c.Agent = agent
	return &c
}

func (c *ConsulOperator) Fix() {
	if c.Agent == "" {
		c.Agent = "localhost:8500"
	}
	if c.Path == "" {
		c.Path = CONSUL_HEALTH_PATH
	}
	if c.Port == 0 {
		c.Port = 80
	}
	if c.IP == "" {
		c.IP, _ = qgoutils.GetHostIP()
		if c.IP == "" {
			c.IP, _ = qgoutils.GetInternalIP()
		}
	}
	if c.Interval == "" {
		c.Interval = "10s"
	}
}

func (c *ConsulOperator) Ping() error {
	var retErr error
	c.once.Do(func() {
		consulCfg := consulapi.DefaultConfig()
		consulCfg.Address = c.Agent
		consul, err := consulapi.NewClient(consulCfg)
		retErr = err
		if err != nil {
			logrus.Error("New consul client error: ", err)
			return
		}
		c.consul = consul
	})
	return retErr
}

func (c *ConsulOperator) Get(name string) ([]byte, error) {
	consul := c.consul
	kv := consul.KV()
	pair, _, err := kv.Get(name, nil)
	if err != nil {
		return nil, err
	}
	if pair == nil {
		return nil, errors.New("NOT EXIST")
	}
	return pair.Value, nil
}

func (c *ConsulOperator) Put(name string, value []byte) error {
	consul := c.consul
	kv := consul.KV()
	pair := &consulapi.KVPair{
		Key:   name,
		Value: value,
	}
	_, err := kv.Put(pair, nil)
	return err
}

func (c *ConsulOperator) Delete(name string) error {
	consul := c.consul
	kv := consul.KV()
	_, err := kv.Delete(name, nil)
	return err
}

func (c *ConsulOperator) Acquire(key string, stopChan <-chan struct{}) error {
	lock, exist := c.lockmap[key]
	var err error
	if !exist {
		lock, err = c.consul.LockKey(key)
		if err != nil {
			logrus.Error("consul Require Lockkey error ", err)
			return err
		}
		c.lockmap[key] = lock
	}
	_, err = lock.Lock(stopChan)
	if err != nil {
		logrus.Error("consul Require lock.Lock error ", err)
		return err
	}
	return nil
}

func (c *ConsulOperator) Release(key string) error {
	lock, exist := c.lockmap[key]
	if !exist {
		return errors.Errorf("%v lock not exist", key)
	}
	err := lock.Unlock()
	if err != nil {
		logrus.Error("consul Require lock.Lock error ", err)
		return err
	}
	return nil
}

func (c *ConsulOperator) RegisterService() error {
	consul := c.consul
	agent := consul.Agent()
	check := consulapi.AgentServiceCheck{
		Interval: c.Interval,
		HTTP:     fmt.Sprintf("http://%s:%d/%s", c.IP, c.Port, c.Path),
		DeregisterCriticalServiceAfter: "1m",
	}

	service := &consulapi.AgentServiceRegistration{
		ID:      c.Name,
		Name:    c.Name,
		Check:   &check,
		Address: c.IP,
		Port:    c.Port,
	}
	txt, _ := json.MarshalIndent(*service, " ", "\t")
	fmt.Println("register service:", string(txt))
	return agent.ServiceRegister(service)
}

func (c *ConsulOperator) DeregisterService() error {
	consul := c.consul
	agent := consul.Agent()
	return agent.ServiceDeregister(c.Name)
}

func (c *ConsulOperator) PrintServices(name string) error {
	consul := c.consul
	catalog := consul.Catalog()
	services, _, err := catalog.Service(name, "", nil)
	if err != nil {
		return err
	}
	fmt.Println("LIST services:")
	for _, v := range services {
		txt, _ := json.MarshalIndent(v, " ", "\t")
		fmt.Println(string(txt))
	}
	return err
}

func (c *ConsulOperator) ListServices(name string) ([]*consulapi.CatalogService, error) {
	consul := c.consul
	catalog := consul.Catalog()
	services, _, err := catalog.Service(name, "", nil)
	return services, err
}

func (c *ConsulOperator) Save() {
	yamlconfig.Save(*c, "consul.yml")
}
<commit_msg>consul ListServices, ListService<commit_after>package consul

import (
	"encoding/json"
	"fmt"

	"sync"

	"github.com/Sirupsen/logrus"
	qgoutils "github.com/chennqqi/goutils/utils"
	"github.com/chennqqi/goutils/yamlconfig"
	consulapi "github.com/hashicorp/consul/api"
	"github.com/pkg/errors"
)

const (
	CONSUL_HEALTH_PATH = "health"
)

type ConsulOperator struct {
	Agent    string `json:"agent,omitempty" yaml:"agent,omitempty"`
	IP       string `json:"ip" yaml:"ip"`
	Port     int    `json:"port" yaml:"port"`
	Name     string `json:"Name" yaml:"Name"`
	Path     string `json:"path,omitempty" yaml:"path,omitempty"`
	Interval string `json:"interval,omitempty" yaml:"interval,omitempty"`

	//for check
	consul  *consulapi.Client `json:"-" yaml:"-"`
	once    sync.Once
	lockmap map[string]*consulapi.Lock
}

func NewConsulOp(agent string) *ConsulOperator {
	var c ConsulOperator
	c.lockmap = make(map[string]*consulapi.Lock)
	c.Agent = agent
	return &c
}

func (c *ConsulOperator) Fix() {
	if c.Agent == "" {
		c.Agent = "localhost:8500"
	}
	if c.Path == "" {
		c.Path = CONSUL_HEALTH_PATH
	}
	if c.Port == 0 {
		c.Port = 80
	}
	if c.IP == "" {
		c.IP, _ = qgoutils.GetHostIP()
		if c.IP == "" {
			c.IP, _ = qgoutils.GetInternalIP()
		}
	}
	if c.Interval == "" {
		c.Interval = "10s"
	}
}

func (c *ConsulOperator) Ping() error {
	var retErr error
	c.once.Do(func() {
		consulCfg := consulapi.DefaultConfig()
		consulCfg.Address = c.Agent
		consul, err := consulapi.NewClient(consulCfg)
		retErr = err
		if err != nil {
			logrus.Error("New consul client error: ", err)
			return
		}
		c.consul = consul
	})
	return retErr
}

func (c *ConsulOperator) Get(name string) ([]byte, error) {
	consul := c.consul
	kv := consul.KV()
	pair, _, err := kv.Get(name, nil)
	if err != nil {
		return nil, err
	}
	if pair == nil {
		return nil, errors.New("NOT EXIST")
	}
	return pair.Value, nil
}

func (c *ConsulOperator) Put(name string, value []byte) error {
	consul := c.consul
	kv := consul.KV()
	pair := &consulapi.KVPair{
		Key:   name,
		Value: value,
	}
	_, err := kv.Put(pair, nil)
	return err
}

func (c *ConsulOperator) Delete(name string) error {
	consul := c.consul
	kv := consul.KV()
	_, err := kv.Delete(name, nil)
	return err
}

func (c *ConsulOperator) Acquire(key string, stopChan <-chan struct{}) error {
	lock, exist := c.lockmap[key]
	var err error
	if !exist {
		lock, err = c.consul.LockKey(key)
		if err != nil {
			logrus.Error("consul Require Lockkey error ", err)
			return err
		}
		c.lockmap[key] = lock
	}
	_, err = lock.Lock(stopChan)
	if err != nil {
		logrus.Error("consul Require lock.Lock error ", err)
		return err
	}
	return nil
}

func (c *ConsulOperator) Release(key string) error {
	lock, exist := c.lockmap[key]
	if !exist {
		return errors.Errorf("%v lock not exist", key)
	}
	err := lock.Unlock()
	if err != nil {
		logrus.Error("consul Require lock.Lock error ", err)
		return err
	}
	return nil
}

func (c *ConsulOperator) RegisterService() error {
	consul := c.consul
	agent := consul.Agent()
	check := consulapi.AgentServiceCheck{
		Interval: c.Interval,
		HTTP:     fmt.Sprintf("http://%s:%d/%s", c.IP, c.Port, c.Path),
		DeregisterCriticalServiceAfter: "1m",
	}

	service := &consulapi.AgentServiceRegistration{
		ID:      c.Name,
		Name:    c.Name,
		Check:   &check,
		Address: c.IP,
		Port:    c.Port,
	}
	txt, _ := json.MarshalIndent(*service, " ", "\t")
	fmt.Println("register service:", string(txt))
	return agent.ServiceRegister(service)
}

func (c *ConsulOperator) DeregisterService() error {
	consul := c.consul
	agent := consul.Agent()
	return agent.ServiceDeregister(c.Name)
}

func (c *ConsulOperator) PrintServices(name string) error {
	consul := c.consul
	catalog := consul.Catalog()
	services, _, err := catalog.Service(name, "", nil)
	if err != nil {
		return err
	}
	fmt.Println("LIST services:")
	for _, v := range services {
		txt, _ := json.MarshalIndent(v, " ", "\t")
		fmt.Println(string(txt))
	}
	return err
}

func (c *ConsulOperator) ListService(name string) ([]*consulapi.CatalogService, error) {
	consul := c.consul
	catalog := consul.Catalog()
	services, _, err := catalog.Service(name, "", nil)
	return services, err
}

func (c *ConsulOperator) ListServices() (map[string][]string, error) {
	consul := c.consul
	catalog := consul.Catalog()
	services, _, err := catalog.Services(nil)
	return services, err
}

func (c *ConsulOperator) Save() {
	yamlconfig.Save(*c, "consul.yml")
}
<|endoftext|>


<commit_before>// +build cgo

package gpkg

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	"github.com/arolek/tegola/basic"
	"github.com/terranodo/tegola"
	"github.com/terranodo/tegola/geom"
	"github.com/terranodo/tegola/geom/encoding/wkb"
	"github.com/terranodo/tegola/internal/log"
	"github.com/terranodo/tegola/provider"
)

const (
	Name                 = "gpkg"
	DefaultSRID          = tegola.WebMercator
	DefaultIDFieldName   = "fid"
	DefaultGeomFieldName = "geom"
)

//	config keys
const (
	ConfigKeyFilePath    = "filepath"
	ConfigKeyLayers      = "layers"
	ConfigKeyLayerName   = "name"
	ConfigKeyTableName   = "tablename"
	ConfigKeySQL         = "sql"
	ConfigKeyGeomIDField = "id_fieldname"
	ConfigKeyFields      = "fields"
)

func decodeGeometry(bytes []byte) (*BinaryHeader, geom.Geometry, error) {
	h, err := NewBinaryHeader(bytes)
	if err != nil {
		log.Error("error decoding geometry header: %v", err)
		return h, nil, err
	}

	geo, err := wkb.DecodeBytes(bytes[h.Size():])
	if err != nil {
		log.Error("error decoding geometry: %v", err)
		return h, nil, err
	}

	return h, geo, nil
}

type Provider struct {
	// path to the geopackage file
	Filepath string
	// map of layer name and corrosponding sql
	layers map[string]Layer
	// reference to the database connection
	db *sql.DB
}

func (p *Provider) Layers() ([]provider.LayerInfo, error) {
	log.Debug("attempting gpkg.Layers()")

	ls := make([]provider.LayerInfo, len(p.layers))

	var i int
	for _, player := range p.layers {
		ls[i] = player
		i++
	}

	log.Debugf("returning LayerInfo array: %v", ls)

	return ls, nil
}

func (p *Provider) TileFeatures(ctx context.Context, layer string, tile provider.Tile, fn func(f *provider.Feature) error) error {
	log.Debugf("fetching layer %v", layer)

	pLayer := p.layers[layer]

	//	read the tile extent
	bufferedExtent, tileSRID := tile.BufferedExtent()

	// TODO: leverage minx/y maxx/y methods once the BufferedExtent returns a geom.Extent type
	tileBBox := geom.BoundingBox{
		{bufferedExtent[0][0], bufferedExtent[0][1]}, //minx, miny
		{bufferedExtent[1][0], bufferedExtent[1][1]}, //maxx, maxy
	}

	// TODO(arolek): reimplement once the geom package has reprojection
	// check if the SRID of the layer differes from that of the tile. tileSRID is assumed to always be WebMercator
	if pLayer.srid != tileSRID {
		minGeo, err := basic.FromWebMercator(int(pLayer.srid), basic.Point{bufferedExtent[0][0], bufferedExtent[0][1]})
		if err != nil {
			return fmt.Errorf("error converting point: %v ", err)
		}

		maxGeo, err := basic.FromWebMercator(int(pLayer.srid), basic.Point{bufferedExtent[1][0], bufferedExtent[1][1]})
		if err != nil {
			return fmt.Errorf("error converting point: %v ", err)
		}

		tileBBox = geom.BoundingBox{
			{minGeo.AsPoint().X(), minGeo.AsPoint().Y()},
			{maxGeo.AsPoint().X(), maxGeo.AsPoint().Y()},
		}
	}

	var qtext string

	if pLayer.tablename != "" {
		// If layer was specified via "tablename" in config, construct query.
		rtreeTablename := fmt.Sprintf("rtree_%v_geom", pLayer.tablename)

		selectClause := fmt.Sprintf("SELECT `%v` AS fid, `%v` AS geom", pLayer.idFieldname, pLayer.geomFieldname)

		for _, tf := range pLayer.tagFieldnames {
			selectClause += fmt.Sprintf(", `%v`", tf)
		}

		// l - layer table, si - spatial index
		qtext = fmt.Sprintf("%v FROM %v l JOIN %v si ON l.%v = si.id WHERE geom IS NOT NULL AND !BBOX!", selectClause, pLayer.tablename, rtreeTablename, pLayer.idFieldname)

		z, _, _ := tile.ZXY()
		qtext = replaceTokens(qtext, z, tileBBox)
	} else {
		// If layer was specified via "sql" in config, collect it
		z, _, _ := tile.ZXY()
		qtext = replaceTokens(pLayer.sql, z, tileBBox)
	}

	log.Debugf("qtext: %v", qtext)

	rows, err := p.db.Query(qtext)
	if err != nil {
		log.Errorf("err during query: %v - %v", qtext, err)
		return err
	}
	defer rows.Close()

	cols, err := rows.Columns()
	if err != nil {
		return err
	}

	for rows.Next() {
		// check if the context cancelled or timed out
		if ctx.Err() != nil {
			return ctx.Err()
		}

		vals := make([]interface{}, len(cols))
		valPtrs := make([]interface{}, len(cols))
		for i := 0; i < len(cols); i++ {
			valPtrs[i] = &vals[i]
		}

		if err = rows.Scan(valPtrs...); err != nil {
			log.Errorf("err reading row values: %v", err)
			return err
		}

		feature := provider.Feature{
			Tags: map[string]interface{}{},
		}

		for i := range cols {
			// check if the context cancelled or timed out
			if ctx.Err() != nil {
				return ctx.Err()
			}
			if vals[i] == nil {
				continue
			}

			switch cols[i] {
			case pLayer.idFieldname:
				feature.ID, err = provider.ConvertFeatureID(vals[i])
				if err != nil {
					return err
				}

			case pLayer.geomFieldname:
				log.Debugf("extracting geopackage geometry header.", vals[i])

				geomData, ok := vals[i].([]byte)
				if !ok {
					log.Errorf("unexpected column type for geom field. got %t", vals[i])
					return errors.New("unexpected column type for geom field. expected blob")
				}

				h, geo, err := decodeGeometry(geomData)
				if err != nil {
					return err
				}

				feature.SRID = uint64(h.SRSId())
				feature.Geometry = geo

			case "minx", "miny", "maxx", "maxy", "min_zoom", "max_zoom":
				// Skip these columns used for bounding box and zoom filtering
				continue

			default:
				// Grab any non-nil, non-id, non-bounding box, & non-geometry column as a tag
				switch v := vals[i].(type) {
				case []uint8:
					asBytes := make([]byte, len(v))
					for j := 0; j < len(v); j++ {
						asBytes[j] = v[j]
					}

					feature.Tags[cols[i]] = string(asBytes)
				case int64:
					feature.Tags[cols[i]] = v
				default:
					// TODO(arolek): return this error?
					log.Errorf("unexpected type for sqlite column data: %v: %T", cols[i], v)
				}
			}
		}

		//	pass the feature to the provided call back
		if err = fn(&feature); err != nil {
			return err
		}
	}

	return nil
}

// Close will close the Provider's database connection
func (p *Provider) Close() error {
	return p.db.Close()
}

type GeomTableDetails struct {
	geomFieldname string
	geomType      geom.Geometry
	srid          uint64
	bbox          geom.BoundingBox
}

type GeomColumn struct {
	name         string
	geometryType string
	geom         geom.Geometry // to populate Layer.geomType
	srsId        int
}

func geomNameToGeom(name string) (geom.Geometry, error) {
	switch name {
	case "POINT":
		return geom.Point{}, nil
	case "LINESTRING":
		return geom.LineString{}, nil
	case "POLYGON":
		return geom.Polygon{}, nil
	case "MULTIPOINT":
		return geom.MultiPoint{}, nil
	case "MULTILINESTRING":
		return geom.MultiLineString{}, nil
	case "MULTIPOLYGON":
		return geom.MultiPolygon{}, nil
	}

	return nil, fmt.Errorf("unsupported geometry type: %v", name)
}
<commit_msg>fixed incorrect import path. #161<commit_after>// +build cgo

package gpkg

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	"github.com/terranodo/tegola"
	"github.com/terranodo/tegola/basic"
	"github.com/terranodo/tegola/geom"
	"github.com/terranodo/tegola/geom/encoding/wkb"
	"github.com/terranodo/tegola/internal/log"
	"github.com/terranodo/tegola/provider"
)

const (
	Name                 = "gpkg"
	DefaultSRID          = tegola.WebMercator
	DefaultIDFieldName   = "fid"
	DefaultGeomFieldName = "geom"
)

//	config keys
const (
	ConfigKeyFilePath    = "filepath"
	ConfigKeyLayers      = "layers"
	ConfigKeyLayerName   = "name"
	ConfigKeyTableName   = "tablename"
	ConfigKeySQL         = "sql"
	ConfigKeyGeomIDField = "id_fieldname"
	ConfigKeyFields      = "fields"
)

func decodeGeometry(bytes []byte) (*BinaryHeader, geom.Geometry, error) {
	h, err := NewBinaryHeader(bytes)
	if err != nil {
		log.Error("error decoding geometry header: %v", err)
		return h, nil, err
	}

	geo, err := wkb.DecodeBytes(bytes[h.Size():])
	if err != nil {
		log.Error("error decoding geometry: %v", err)
		return h, nil, err
	}

	return h, geo, nil
}

type Provider struct {
	// path to the geopackage file
	Filepath string
	// map of layer name and corrosponding sql
	layers map[string]Layer
	// reference to the database connection
	db *sql.DB
}

func (p *Provider) Layers() ([]provider.LayerInfo, error) {
	log.Debug("attempting gpkg.Layers()")

	ls := make([]provider.LayerInfo, len(p.layers))

	var i int
	for _, player := range p.layers {
		ls[i] = player
		i++
	}

	log.Debugf("returning LayerInfo array: %v", ls)

	return ls, nil
}

func (p *Provider) TileFeatures(ctx context.Context, layer string, tile provider.Tile, fn func(f *provider.Feature) error) error {
	log.Debugf("fetching layer %v", layer)

	pLayer := p.layers[layer]

	//	read the tile extent
	bufferedExtent, tileSRID := tile.BufferedExtent()

	// TODO: leverage minx/y maxx/y methods once the BufferedExtent returns a geom.Extent type
	tileBBox := geom.BoundingBox{
		{bufferedExtent[0][0], bufferedExtent[0][1]}, //minx, miny
		{bufferedExtent[1][0], bufferedExtent[1][1]}, //maxx, maxy
	}

	// TODO(arolek): reimplement once the geom package has reprojection
	// check if the SRID of the layer differes from that of the tile. tileSRID is assumed to always be WebMercator
	if pLayer.srid != tileSRID {
		minGeo, err := basic.FromWebMercator(int(pLayer.srid), basic.Point{bufferedExtent[0][0], bufferedExtent[0][1]})
		if err != nil {
			return fmt.Errorf("error converting point: %v ", err)
		}

		maxGeo, err := basic.FromWebMercator(int(pLayer.srid), basic.Point{bufferedExtent[1][0], bufferedExtent[1][1]})
		if err != nil {
			return fmt.Errorf("error converting point: %v ", err)
		}

		tileBBox = geom.BoundingBox{
			{minGeo.AsPoint().X(), minGeo.AsPoint().Y()},
			{maxGeo.AsPoint().X(), maxGeo.AsPoint().Y()},
		}
	}

	var qtext string

	if pLayer.tablename != "" {
		// If layer was specified via "tablename" in config, construct query.
		rtreeTablename := fmt.Sprintf("rtree_%v_geom", pLayer.tablename)

		selectClause := fmt.Sprintf("SELECT `%v` AS fid, `%v` AS geom", pLayer.idFieldname, pLayer.geomFieldname)

		for _, tf := range pLayer.tagFieldnames {
			selectClause += fmt.Sprintf(", `%v`", tf)
		}

		// l - layer table, si - spatial index
		qtext = fmt.Sprintf("%v FROM %v l JOIN %v si ON l.%v = si.id WHERE geom IS NOT NULL AND !BBOX!", selectClause, pLayer.tablename, rtreeTablename, pLayer.idFieldname)

		z, _, _ := tile.ZXY()
		qtext = replaceTokens(qtext, z, tileBBox)
	} else {
		// If layer was specified via "sql" in config, collect it
		z, _, _ := tile.ZXY()
		qtext = replaceTokens(pLayer.sql, z, tileBBox)
	}

	log.Debugf("qtext: %v", qtext)

	rows, err := p.db.Query(qtext)
	if err != nil {
		log.Errorf("err during query: %v - %v", qtext, err)
		return err
	}
	defer rows.Close()

	cols, err := rows.Columns()
	if err != nil {
		return err
	}

	for rows.Next() {
		// check if the context cancelled or timed out
		if ctx.Err() != nil {
			return ctx.Err()
		}

		vals := make([]interface{}, len(cols))
		valPtrs := make([]interface{}, len(cols))
		for i := 0; i < len(cols); i++ {
			valPtrs[i] = &vals[i]
		}

		if err = rows.Scan(valPtrs...); err != nil {
			log.Errorf("err reading row values: %v", err)
			return err
		}

		feature := provider.Feature{
			Tags: map[string]interface{}{},
		}

		for i := range cols {
			// check if the context cancelled or timed out
			if ctx.Err() != nil {
				return ctx.Err()
			}
			if vals[i] == nil {
				continue
			}

			switch cols[i] {
			case pLayer.idFieldname:
				feature.ID, err = provider.ConvertFeatureID(vals[i])
				if err != nil {
					return err
				}

			case pLayer.geomFieldname:
				log.Debugf("extracting geopackage geometry header.", vals[i])

				geomData, ok := vals[i].([]byte)
				if !ok {
					log.Errorf("unexpected column type for geom field. got %t", vals[i])
					return errors.New("unexpected column type for geom field. expected blob")
				}

				h, geo, err := decodeGeometry(geomData)
				if err != nil {
					return err
				}

				feature.SRID = uint64(h.SRSId())
				feature.Geometry = geo

			case "minx", "miny", "maxx", "maxy", "min_zoom", "max_zoom":
				// Skip these columns used for bounding box and zoom filtering
				continue

			default:
				// Grab any non-nil, non-id, non-bounding box, & non-geometry column as a tag
				switch v := vals[i].(type) {
				case []uint8:
					asBytes := make([]byte, len(v))
					for j := 0; j < len(v); j++ {
						asBytes[j] = v[j]
					}

					feature.Tags[cols[i]] = string(asBytes)
				case int64:
					feature.Tags[cols[i]] = v
				default:
					// TODO(arolek): return this error?
					log.Errorf("unexpected type for sqlite column data: %v: %T", cols[i], v)
				}
			}
		}

		//	pass the feature to the provided call back
		if err = fn(&feature); err != nil {
			return err
		}
	}

	return nil
}

// Close will close the Provider's database connection
func (p *Provider) Close() error {
	return p.db.Close()
}

type GeomTableDetails struct {
	geomFieldname string
	geomType      geom.Geometry
	srid          uint64
	bbox          geom.BoundingBox
}

type GeomColumn struct {
	name         string
	geometryType string
	geom         geom.Geometry // to populate Layer.geomType
	srsId        int
}

func geomNameToGeom(name string) (geom.Geometry, error) {
	switch name {
	case "POINT":
		return geom.Point{}, nil
	case "LINESTRING":
		return geom.LineString{}, nil
	case "POLYGON":
		return geom.Polygon{}, nil
	case "MULTIPOINT":
		return geom.MultiPoint{}, nil
	case "MULTILINESTRING":
		return geom.MultiLineString{}, nil
	case "MULTIPOLYGON":
		return geom.MultiPolygon{}, nil
	}

	return nil, fmt.Errorf("unsupported geometry type: %v", name)
}
<|endoftext|>


<commit_before>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"math/big"
	"testing"
)

func TestFunctions(t *testing.T) {
	badCalls := []string{
		"a()", "a(1, 2, 3)", "2 + 6 * (a(1, 2))", "abs(1, 2)", "abs()",
		"max(1)", "min(2)",
	}

	for _, expr := range badCalls {
		_, err := Eval(expr)
		if err == nil {
			t.Error("expected error on bad function call")
		}
	}

	okCalls := []string{
		"abs(-300)", "max(8, 8)", "8 * cos(pi) - 6", "tan(8 * 8 * (7**7))",
		"tan(cos(8) / sin(3))",
	}

	for _, expr := range okCalls {
		_, err := Eval(expr)
		if err != nil {
			t.Errorf("unexpected error on ok function call: %s", err)
		}
	}
}

func TestFunctionsResult(t *testing.T) {
	calls := map[string]*big.Rat{
		"abs(-700)":                         big.NewRat(700, 1),
		"ceil(813.23)":                      big.NewRat(814, 1),
		"ceil(ceil(10 ** 16 + 0.1))":        big.NewRat(10000000000000001, 1),
		"floor(813.23)":                     big.NewRat(813, 1),
		"sin(74)":                           big.NewRat(-8873408663100473, 9007199254740992),
		"cos(74)":                           big.NewRat(6186769253457135, 36028797018963968),
		"tan(74)":                           big.NewRat(-6459313142528259, 1125899906842624),
		"asin(-1)":                          big.NewRat(-884279719003555, 562949953421312),
		"acos(-1)":                          big.NewRat(884279719003555, 281474976710656),
		"atan(-1)":                          big.NewRat(-884279719003555, 1125899906842624),
		"ln(3*100)":                         big.NewRat(802736019608251, 140737488355328),
		"log(50)":                           big.NewRat(59777192800323, 35184372088832),
		"logn(2, 50)":                       big.NewRat(6354417158300529, 1125899906842624),
		"max(5, 8)":                         big.NewRat(8, 1),
		"min(5, 8)":                         big.NewRat(5, 1),
		"sqrt(144)":                         big.NewRat(12, 1),
		"tan(144) + tan(-3) + sin(5)":       big.NewRat(-49720712606960177, 36028797018963968),
		"fact(6) * fact(7) == fact(10)":     big.NewRat(1, 1),
		"fact(6.5) * fact(7.3) == fact(10)": big.NewRat(1, 1),
	}

	for expr, expected := range calls {
		res, err := Eval(expr)
		if err != nil {
			t.Errorf("unexpected error on ok function call: %s", err)
		}

		if res.Cmp(expected) != 0 {
			t.Errorf("wrong result in function call '%s' (expected %s, got %s)",
				expr, expected, res)
		}
	}
}
<commit_msg>Add negative floor test cases<commit_after>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"math/big"
	"testing"
)

func TestFunctions(t *testing.T) {
	badCalls := []string{
		"a()", "a(1, 2, 3)", "2 + 6 * (a(1, 2))", "abs(1, 2)", "abs()",
		"max(1)", "min(2)",
	}

	for _, expr := range badCalls {
		_, err := Eval(expr)
		if err == nil {
			t.Error("expected error on bad function call")
		}
	}

	okCalls := []string{
		"abs(-300)", "max(8, 8)", "8 * cos(pi) - 6", "tan(8 * 8 * (7**7))",
		"tan(cos(8) / sin(3))",
	}

	for _, expr := range okCalls {
		_, err := Eval(expr)
		if err != nil {
			t.Errorf("unexpected error on ok function call: %s", err)
		}
	}
}

func TestFunctionsResult(t *testing.T) {
	calls := map[string]*big.Rat{
		"abs(-700)":                         big.NewRat(700, 1),
		"ceil(813.23)":                      big.NewRat(814, 1),
		"ceil(ceil(10 ** 16 + 0.1))":        big.NewRat(10000000000000001, 1),
		"floor(813.23)":                     big.NewRat(813, 1),
		"floor(-50.23)":                     big.NewRat(-51, 1),
		"floor(-50)":                        big.NewRat(-50, 1),
		"sin(74)":                           big.NewRat(-8873408663100473, 9007199254740992),
		"cos(74)":                           big.NewRat(6186769253457135, 36028797018963968),
		"tan(74)":                           big.NewRat(-6459313142528259, 1125899906842624),
		"asin(-1)":                          big.NewRat(-884279719003555, 562949953421312),
		"acos(-1)":                          big.NewRat(884279719003555, 281474976710656),
		"atan(-1)":                          big.NewRat(-884279719003555, 1125899906842624),
		"ln(3*100)":                         big.NewRat(802736019608251, 140737488355328),
		"log(50)":                           big.NewRat(59777192800323, 35184372088832),
		"logn(2, 50)":                       big.NewRat(6354417158300529, 1125899906842624),
		"max(5, 8)":                         big.NewRat(8, 1),
		"min(5, 8)":                         big.NewRat(5, 1),
		"sqrt(144)":                         big.NewRat(12, 1),
		"tan(144) + tan(-3) + sin(5)":       big.NewRat(-49720712606960177, 36028797018963968),
		"fact(6) * fact(7) == fact(10)":     big.NewRat(1, 1),
		"fact(6.5) * fact(7.3) == fact(10)": big.NewRat(1, 1),
	}

	for expr, expected := range calls {
		res, err := Eval(expr)
		if err != nil {
			t.Errorf("unexpected error on ok function call: %s", err)
		}

		if res.Cmp(expected) != 0 {
			t.Errorf("wrong result in function call '%s' (expected %s, got %s)",
				expr, expected, res)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/mattn/go-runewidth"
	"github.com/rivo/uniseg"
	"log"
	"math/rand"
	"time"

	irc "github.com/fluffle/goirc/client"
	"github.com/nsf/termbox-go"
	"github.com/sosodev/twitchChatCLI/state"
	"github.com/sosodev/twitchChatCLI/twitch"

	"os"
	"strings"
)

var (
	userInput string
)

func main() {
	// setup the debugging log if requested
	if os.Getenv("debug") == "true" {
		logFile, err := os.OpenFile("debug.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			panic(fmt.Sprintf("failed to open log file: %s", err))
		}
		defer logFile.Close()

		log.SetOutput(logFile)
	}

	// seed the random number generator
	rand.Seed(time.Now().UTC().UnixNano())

	// grab the channel name from the input args
	if len(os.Args) < 2 {
		fmt.Println("usage: twitchChatCli [channel-name]")
		os.Exit(1)
	}
	channel := "#" + strings.ToLower(os.Args[1])

	// initalize termbox (the thing that renders stuff in the terminal)
	if err := termbox.Init(); err != nil {
		panic(fmt.Sprintf("failed to initialize termbox: %s", err))
	}
	defer termbox.Close()
	termbox.SetInputMode(termbox.InputEsc)

	// creating the twitch object actually handles the Twitch authentication stuff
	twitch, err := twitch.New()
	if err != nil {
		panic(fmt.Sprintf("failed to get authorization from Twitch: %s", err))
	}

	username, err := twitch.Username()
	if err != nil {
		panic(fmt.Sprintf("failed to get username from Twitch: %s", err))
	}
	username = strings.ToLower(username)

	// get the IRC config
	cfg, err := twitch.IrcConfig()
	if err != nil {
		panic(fmt.Sprintf("failed to initialize IRC configuration: %s", err))
	}

	// create the IRC client
	client := irc.Client(cfg)
	client.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
		conn.Join(channel)
	})

	// tbPrint prints a string with termbox
	tbPrint := func(x int, y int, foreground termbox.Attribute, background termbox.Attribute, message string) {
		graphemes := uniseg.NewGraphemes(message)
		for graphemes.Next() {
			for _, graphemeRune := range graphemes.Runes() {
				termbox.SetCell(x, y, graphemeRune, foreground, background)
				x += runewidth.RuneWidth(graphemeRune)
			}
		}
	}

	// drawLine draws a state.ChatLine on the given y line
	drawLine := func(line state.ChatLine, y int) {
		// the nick portion of the line can either be "nick: " or indented "     "
		nick := func() string {
			if line.ShowNick {
				return fmt.Sprintf("%s: ", line.Nick)
			}

			emptySpace := "  "
			for range line.Nick {
				emptySpace += " "
			}

			return emptySpace
		}()

		// draw the nick portion of the line
		tbPrint(1, y, line.NickColor, termbox.ColorDefault, nick)

		var foreground termbox.Attribute
		background := termbox.ColorDefault
		if strings.Contains(line.Line, "@"+username) {
			foreground = termbox.ColorBlack
			background = termbox.ColorWhite
		} else {
			foreground = termbox.ColorWhite
		}

		// draw the body of the line
		tbPrint(len(nick)+1, y, foreground, background, line.Line)
	}

	// drawClient is a function that... draws the client
	drawClient := func() {
		// clear the terminal
		termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

		width, height := termbox.Size()

		// draw the escape message
		if os.Getenv("CLEAN") != "true" {
			tbPrint(width-18, 0, termbox.ColorLightBlue, termbox.ColorDefault, "Press ESC to quit")
		}

		// iterate through all of the lines in reverse (to draw them newest to oldest)
		state.ReverseEachLine(func(position int, line state.ChatLine) {
			// no pointless iteration here
			if position > height-2 {
				return
			}

			drawLine(line, height-2-position)
		})

		// draw the user's input at the bottom of the terminal
		if os.Getenv("CLEAN") != "true" {
			tbPrint(1, height-1, state.NickColor(username), termbox.ColorDefault, fmt.Sprintf("%s: %s", username, userInput))
		}

		// flush the termbox buffer to the terminal
		err = termbox.Flush()
		if err != nil {
			panic(fmt.Sprintf("failed to flush termbox: %s", err))
		}
	}

	// handle incoming messages by adding them to the state and redrawing the client
	client.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) {
		state.NewMessage(line.Nick, true, line.Args[1])
		drawClient()
	})

	// startup ye olde IRC client
	if err := client.Connect(); err != nil {
		panic(fmt.Sprintf("failed to connect to irc: %s", err))
	}

	// do an inital drawing
	drawClient()

	// big event handler loop
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				os.Exit(0)
			case termbox.KeySpace:
				userInput += " "
			case termbox.KeyEnter:
				if len(userInput) > 2 {
					state.NewMessage(username, true, userInput)
					client.Privmsg(channel, userInput)
					userInput = ""
				}
			case termbox.KeyBackspace2:
				if len(userInput) > 0 {
					userInput = userInput[0 : len(userInput)-1]
				}
			case termbox.KeyBackspace:
				if len(userInput) > 0 {
					userInput = userInput[0 : len(userInput)-1]
				}
			default:
				if ev.Ch != 0 {
					userInput += string(ev.Ch)
				}
			}
		case termbox.EventError:
			panic(fmt.Sprintf("termbox event error: %s", ev.Err.Error()))
		}

		// draw the client after every handled event
		drawClient()
	}
}
<commit_msg>it worksssss<commit_after>package main

import (
	"fmt"
	"github.com/mattn/go-runewidth"
	"github.com/rivo/uniseg"
	"log"
	"math/rand"
	"time"

	irc "github.com/fluffle/goirc/client"
	"github.com/nsf/termbox-go"
	"github.com/sosodev/twitchChatCLI/state"
	"github.com/sosodev/twitchChatCLI/twitch"

	"os"
	"strings"
)

var (
	userInput string
)

func main() {
	// setup the debugging log if requested
	if os.Getenv("debug") == "true" {
		logFile, err := os.OpenFile("debug.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			panic(fmt.Sprintf("failed to open log file: %s", err))
		}
		defer logFile.Close()

		log.SetOutput(logFile)
	}

	// seed the random number generator
	rand.Seed(time.Now().UTC().UnixNano())

	// grab the channel name from the input args
	if len(os.Args) < 2 {
		fmt.Println("usage: twitchChatCli [channel-name]")
		os.Exit(1)
	}
	channel := "#" + strings.ToLower(os.Args[1])

	// initalize termbox (the thing that renders stuff in the terminal)
	if err := termbox.Init(); err != nil {
		panic(fmt.Sprintf("failed to initialize termbox: %s", err))
	}
	defer termbox.Close()
	termbox.SetInputMode(termbox.InputEsc)

	// creating the twitch object actually handles the Twitch authentication stuff
	twitch, err := twitch.New()
	if err != nil {
		panic(fmt.Sprintf("failed to get authorization from Twitch: %s", err))
	}

	username, err := twitch.Username()
	if err != nil {
		panic(fmt.Sprintf("failed to get username from Twitch: %s", err))
	}
	username = strings.ToLower(username)

	// get the IRC config
	cfg, err := twitch.IrcConfig()
	if err != nil {
		panic(fmt.Sprintf("failed to initialize IRC configuration: %s", err))
	}

	// create the IRC client
	client := irc.Client(cfg)
	client.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
		conn.Join(channel)
	})

	// tbPrint prints a string with termbox
	tbPrint := func(x int, y int, foreground termbox.Attribute, background termbox.Attribute, message string) {
		condition := runewidth.NewCondition()
		condition.StrictEmojiNeutral = false

		graphemes := uniseg.NewGraphemes(message)
		for graphemes.Next() {
			for _, graphemeRune := range graphemes.Runes() {
				termbox.SetCell(x, y, graphemeRune, foreground, background)
				w := runewidth.RuneWidth(graphemeRune)
				if w == 0 || (w == 2 && runewidth.IsAmbiguousWidth(graphemeRune)) {
					w = 1
				}
				x += w
			}
		}
	}

	// drawLine draws a state.ChatLine on the given y line
	drawLine := func(line state.ChatLine, y int) {
		// the nick portion of the line can either be "nick: " or indented "     "
		nick := func() string {
			if line.ShowNick {
				return fmt.Sprintf("%s: ", line.Nick)
			}

			emptySpace := "  "
			for range line.Nick {
				emptySpace += " "
			}

			return emptySpace
		}()

		// draw the nick portion of the line
		tbPrint(1, y, line.NickColor, termbox.ColorDefault, nick)

		var foreground termbox.Attribute
		background := termbox.ColorDefault
		if strings.Contains(line.Line, "@"+username) {
			foreground = termbox.ColorBlack
			background = termbox.ColorWhite
		} else {
			foreground = termbox.ColorWhite
		}

		// draw the body of the line
		tbPrint(len(nick)+1, y, foreground, background, line.Line)
	}

	// drawClient is a function that... draws the client
	drawClient := func() {
		// clear the terminal
		err = termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
		if err != nil {
			panic(fmt.Sprintf("failed to clear termbox buffer: %s\n", err))
		}
		err = termbox.Flush()
		if err != nil {
			panic(fmt.Sprintf("failed to flush termbox buffer: %s\n", err))
		}

		width, height := termbox.Size()

		// draw the escape message
		if os.Getenv("CLEAN") != "true" {
			tbPrint(width-18, 0, termbox.ColorLightBlue, termbox.ColorDefault, "Press ESC to quit")
		}

		// iterate through all of the lines in reverse (to draw them newest to oldest)
		state.ReverseEachLine(func(position int, line state.ChatLine) {
			subtract := 2
			if os.Getenv("CLEAN") == "true" {
				subtract = 1
			}

			// no pointless iteration here
			if position > height-subtract {
				return
			}

			drawLine(line, height-subtract-position)
		})

		// draw the user's input at the bottom of the terminal
		if os.Getenv("CLEAN") != "true" {
			tbPrint(1, height-1, state.NickColor(username), termbox.ColorDefault, fmt.Sprintf("%s: %s", username, userInput))
		}

		// flush the termbox buffer to the terminal
		err = termbox.Flush()
		if err != nil {
			panic(fmt.Sprintf("failed to flush termbox: %s\n", err))
		}
	}

	// handle incoming messages by adding them to the state and redrawing the client
	client.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) {
		state.NewMessage(line.Nick, true, line.Args[1])
		drawClient()
	})

	// startup ye olde IRC client
	if err := client.Connect(); err != nil {
		panic(fmt.Sprintf("failed to connect to irc: %s", err))
	}

	// do an inital drawing
	drawClient()

	// big event handler loop
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				os.Exit(0)
			case termbox.KeySpace:
				userInput += " "
			case termbox.KeyEnter:
				if len(userInput) > 2 {
					state.NewMessage(username, true, userInput)
					client.Privmsg(channel, userInput)
					userInput = ""
				}
			case termbox.KeyBackspace2:
				if len(userInput) > 0 {
					userInput = userInput[0 : len(userInput)-1]
				}
			case termbox.KeyBackspace:
				if len(userInput) > 0 {
					userInput = userInput[0 : len(userInput)-1]
				}
			default:
				if ev.Ch != 0 {
					userInput += string(ev.Ch)
				}
			}
		case termbox.EventError:
			panic(fmt.Sprintf("termbox event error: %s", ev.Err.Error()))
		}

		// draw the client after every handled event
		drawClient()
	}
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"errors"
	"fmt"
	"time"
	"strconv"

	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"

)

// TnT is a high level smart contract that collaborate together business artifact based smart contracts
type TnT struct {
}
var assemblyIndexStr = "_assemblyIndex" // Store Key value pair for Assembly
// Assembly Line Structure
type AssemblyLine struct{
	AssemblyId string `json:"assemblyId"`
	DeviceSerialNo string `json:"deviceSerialNo"`
	DeviceType string `json:"deviceType"`
	//FilamentBatchId string `json:"filamentBatchId"`
	//LedBatchId string `json:"ledBatchId"`
	//CircuitBoardBatchId string `json:"circuitBoardBatchId"`
	//WireBatchId string `json:"wireBatchId"`
	//CasingBatchId string `json:"casingBatchId"`
	//AdaptorBatchId string `json:"adaptorBatchId"`
	//StickPodBatchId string `json:"stickPodBatchId"`
	//ManufacturingPlant string `json:"manufacturingPlant"`
	AssemblyStatus string `json:"assemblyStatus"`
	//AssemblyCreationDate string `json:"assemblyCreationDate"`
	AssemblyLastUpdatedOn string `json:"assemblyLastUpdateOn"`
	//AssemblyCreatedBy string `json:"assemblyCreatedBy"`
	//AssemblyLastUpdatedBy string `json:"assemblyLastUpdatedBy"`
	}

// Package Line Structure
type PackageLine struct{
	CaseId string `json:"caseId"`
	HolderAssemblyId string `json:"holderAssemblyId"`
	ChargerAssemblyId string `json:"chargerAssemblyId"`
	PackageStatus string `json:"packageStatus"`
	PackagingDate string `json:"packagingDate"`
	PackageCreationDate string `json:"packagingCreationDate"`
	PackageLastUpdatedOn string `json:"packageLastUpdateOn"`
	ShippingToAddress string `json:"shippingToAddress"`
	PackageCreatedBy string `json:"packageCreatedBy"`
	PackageLastUpdatedBy string `json:"packageLastUpdatedBy"`
	}

// Init initializes the smart contracts
func (t *TnT) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	var _temp int;
	var err error

	if len(args) != 1 {
			return nil, fmt.Errorf("Incorrect number of arguments. Expecting 1. Got: %d.", len(args))
		}

		// Initialize the chaincode
	_temp, err = strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.New("Expecting integer value ")
	}
	// Write the state to the ledger
	err = stub.PutState("12345678", []byte(strconv.Itoa(_temp)))
	if err != nil {
		return nil, err
	}
	var empty []string
	jsonAsBytes, _ := json.Marshal(empty)								//marshal an emtpy array of strings to clear the index
	err = stub.PutState(assemblyIndexStr, jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}
//API to create an assembly
func (t *TnT) createAssembly(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
if len(args) != 4 {
			return nil, fmt.Errorf("Incorrect number of arguments. Expecting 11. Got: %d.", len(args))
		}

		//var columns []shim.Column
		//_assemblyId:= rand.New(rand.NewSource(99)).Int31

		//Generate the AssemblyId
		//rand.Seed(time.Now().Unix())

		//_assemblyId := strconv.Itoa(rand.Int())
		_assemblyId := args[0]
		_deviceSerialNo:= args[1]
		_deviceType:=args[2]
		//_FilamentBatchId:=args[2]
		//_LedBatchId:=args[3]
		//_CircuitBoardBatchId:=args[4]
		//_WireBatchId:=args[5]
		//_CasingBatchId:=args[6]
		//_AdaptorBatchId:=args[7]
		//_StickPodBatchId:=args[8]
		//_ManufacturingPlant:=args[9]
		_AssemblyStatus:= args[0]

		_time:= time.Now().Local()

		//_AssemblyCreationDate := _time.Format("2006-01-02")
		_AssemblyLastUpdateOn := _time.Format("2006-01-02")
		//_AssemblyCreatedBy := ""
		//_AssemblyLastUpdatedBy := ""

	//check if marble already exists
		assemblyAsBytes, err := stub.GetState(_assemblyId)
		if err != nil {
		return nil, errors.New("Failed to get assembly Id")
		}
		res := AssemblyLine{}
		json.Unmarshal(assemblyAsBytes, &res)
		if res.AssemblyId == _assemblyId{
		fmt.Println("This Assembly arleady exists: " + _assemblyId)
		fmt.Println(res);
		return nil, errors.New("This Assembly arleady exists")				//all stop an Assembly already exists
		}

		str := `{"assemblyId": "` + _assemblyId + `", "deviceSerialNo": "` + _deviceSerialNo + `", "deviceType": "` + _deviceType + `", "assemblyStatus": "`+ _AssemblyStatus +`", "assemblyLastUpdateOn": "` + _AssemblyLastUpdateOn + `"}`

		err = stub.PutState(_assemblyId, []byte(str))								//store assembly with id as key
		if err != nil {
		return nil, err
		}

		//get the assembly index
		assemblyAsBytes, err = stub.GetState(assemblyIndexStr)
		if err != nil {
			return nil, errors.New("Failed to get assembly index")
		}
		var assemblyIndex []string
		json.Unmarshal(assemblyAsBytes, &assemblyIndex)							//un stringify it aka JSON.parse()

		//append
		assemblyIndex = append(assemblyIndex, _assemblyId)								//add assembly id in Index list
		fmt.Println("! Assembly index: ", assemblyIndex)
		jsonAsBytes, _ := json.Marshal(assemblyIndex)
		err = stub.PutState(assemblyIndexStr, jsonAsBytes)						//store assembly

		fmt.Println("Create Assembly")

		return nil, nil

}

//Update Assembly based on Id (Now only status)
func (t *TnT) updateAssemblyByID(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2.")
	}

		_assemblyId := args[0]
		//_deviceSerialNo:= args[1]
		//_deviceType:=args[2]
		//_FilamentBatchId:=args[3]
		//_LedBatchId:=args[4]
		//_CircuitBoardBatchId:=args[5]
		//_WireBatchId:=args[6]
		//_CasingBatchId:=args[7]
		//_AdaptorBatchId:=args[8]
		//_StickPodBatchId:=args[9]
		//_ManufacturingPlant:=args[10]
		_AssemblyStatus:= args[1]
		//_AssemblyCreationDate := args[12]
		//_AssemblyCreatedBy :=  args[13]
		_time:= time.Now().Local()
		_AssemblyLastUpdateOn := _time.Format("2006-01-02")
		//_AssemblyLastUpdatedBy := ""
		str := `{ "assemblyStatus": "` + _AssemblyStatus + `", "assemblyLastUpdateOn": "` +  _AssemblyLastUpdateOn  + `"}`
		err := stub.PutState(_assemblyId, []byte(str))								//write the status into the chaincode state
		if err != nil {
		return nil, err
		}

	return nil, nil

}

//get the Assembly against ID
func (t *TnT) getAssemblyByID(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting AssemblyID to query")
	}

	_assemblyId := args[0]

	valAsbytes, err := stub.GetState(_assemblyId)									//get the var from chaincode state
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " +  _assemblyId  + "\"}"
		return nil, errors.New(jsonResp)
	}

	return valAsbytes, nil

}

// Invoke callback representing the invocation of a chaincode
func (t *TnT) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Printf("Invoke called, determining function")

	// Handle different functions
	if function == "init" {
		fmt.Printf("Function is init")
		return t.Init(stub, function, args)
	} else if function == "createAssembly" {
		fmt.Printf("Function is createAssembly")
		return t.createAssembly(stub, args)
	} else if function == "updateAssemblyByID" {
		fmt.Printf("Function is updateAssemblyByID")
		return t.updateAssemblyByID(stub, args)
	}
	return nil, errors.New("Received unknown function invocation")
}

// query queries the chaincode
func (t *TnT) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Printf("Query called, determining function")

	if function == "getAssemblyByID" {
		t := TnT{}
		return t.getAssemblyByID(stub, args)
	}

	return nil, errors.New("Received unknown function query")
}

	func main() {
	err := shim.Start(new(TnT))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}
<commit_msg>25th May TnT1<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"errors"
	"fmt"
	"time"
	"strconv"

	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"

)

// TnT is a high level smart contract that collaborate together business artifact based smart contracts
type TnT struct {
}
var assemblyIndexStr = "_assemblyIndex" // Store Key value pair for Assembly
// Assembly Line Structure
type AssemblyLine struct{
	AssemblyId string `json:"assemblyId"`
	DeviceSerialNo string `json:"deviceSerialNo"`
	DeviceType string `json:"deviceType"`
	//FilamentBatchId string `json:"filamentBatchId"`
	//LedBatchId string `json:"ledBatchId"`
	//CircuitBoardBatchId string `json:"circuitBoardBatchId"`
	//WireBatchId string `json:"wireBatchId"`
	//CasingBatchId string `json:"casingBatchId"`
	//AdaptorBatchId string `json:"adaptorBatchId"`
	//StickPodBatchId string `json:"stickPodBatchId"`
	//ManufacturingPlant string `json:"manufacturingPlant"`
	AssemblyStatus string `json:"assemblyStatus"`
	//AssemblyCreationDate string `json:"assemblyCreationDate"`
	AssemblyLastUpdatedOn string `json:"assemblyLastUpdateOn"`
	//AssemblyCreatedBy string `json:"assemblyCreatedBy"`
	//AssemblyLastUpdatedBy string `json:"assemblyLastUpdatedBy"`
	}

// Package Line Structure
type PackageLine struct{
	CaseId string `json:"caseId"`
	HolderAssemblyId string `json:"holderAssemblyId"`
	ChargerAssemblyId string `json:"chargerAssemblyId"`
	PackageStatus string `json:"packageStatus"`
	PackagingDate string `json:"packagingDate"`
	PackageCreationDate string `json:"packagingCreationDate"`
	PackageLastUpdatedOn string `json:"packageLastUpdateOn"`
	ShippingToAddress string `json:"shippingToAddress"`
	PackageCreatedBy string `json:"packageCreatedBy"`
	PackageLastUpdatedBy string `json:"packageLastUpdatedBy"`
	}

// Init initializes the smart contracts
func (t *TnT) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

	var _temp int;
	var err error

	if len(args) != 1 {
			return nil, fmt.Errorf("Incorrect number of arguments. Expecting 1. Got: %d.", len(args))
		}

		// Initialize the chaincode
	_temp, err = strconv.Atoi(args[0])
	if err != nil {
		return nil, errors.New("Expecting integer value ")
	}
	// Write the state to the ledger
	err = stub.PutState("12345678", []byte(strconv.Itoa(_temp)))
	if err != nil {
		return nil, err
	}
	var empty []string
	jsonAsBytes, _ := json.Marshal(empty)								//marshal an emtpy array of strings to clear the index
	err = stub.PutState(assemblyIndexStr, jsonAsBytes)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

//API to create an assembly
func (t *TnT) createAssembly(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 4 {
			return nil, fmt.Errorf("Incorrect number of arguments. Expecting 11. Got: %d.", len(args))
		}

		//var columns []shim.Column
		//_assemblyId:= rand.New(rand.NewSource(99)).Int31

		//Generate the AssemblyId
		//rand.Seed(time.Now().Unix())

		//_assemblyId := strconv.Itoa(rand.Int())
		_assemblyId := args[0]
		_deviceSerialNo:= args[1]
		_deviceType:=args[2]
		//_FilamentBatchId:=args[2]
		//_LedBatchId:=args[3]
		//_CircuitBoardBatchId:=args[4]
		//_WireBatchId:=args[5]
		//_CasingBatchId:=args[6]
		//_AdaptorBatchId:=args[7]
		//_StickPodBatchId:=args[8]
		//_ManufacturingPlant:=args[9]
		_AssemblyStatus:= args[0]

		_time:= time.Now().Local()

		//_AssemblyCreationDate := _time.Format("2006-01-02")
		_AssemblyLastUpdateOn := _time.Format("2006-01-02")
		//_AssemblyCreatedBy := ""
		//_AssemblyLastUpdatedBy := ""

	//check if marble already exists
		assemblyAsBytes, err := stub.GetState(_assemblyId)
		if err != nil {
		return nil, errors.New("Failed to get assembly Id")
		}
		res := AssemblyLine{}
		json.Unmarshal(assemblyAsBytes, &res)
		if res.AssemblyId == _assemblyId{
		fmt.Println("This Assembly arleady exists: " + _assemblyId)
		fmt.Println(res);
		return nil, errors.New("This Assembly arleady exists")				//all stop an Assembly already exists
		}

		str := `{"assemblyId": "` + _assemblyId + `", "deviceSerialNo": "` + _deviceSerialNo + `", "deviceType": "` + _deviceType + `", "assemblyStatus": "`+ _AssemblyStatus +`", "assemblyLastUpdateOn": "` + _AssemblyLastUpdateOn + `"}`

		err = stub.PutState(_assemblyId, []byte(str))								//store assembly with id as key
		if err != nil {
		return nil, err
		}
/*
		//get the assembly index
		assemblyAsBytes, err = stub.GetState(assemblyIndexStr)
		if err != nil {
			return nil, errors.New("Failed to get assembly index")
		}
		var assemblyIndex []string
		json.Unmarshal(assemblyAsBytes, &assemblyIndex)							//un stringify it aka JSON.parse()

		//append
		assemblyIndex = append(assemblyIndex, _assemblyId)								//add assembly id in Index list
		fmt.Println("! Assembly index: ", assemblyIndex)
		jsonAsBytes, _ := json.Marshal(assemblyIndex)
		err = stub.PutState(assemblyIndexStr, jsonAsBytes)						//store assembly
*/
		fmt.Println("Create Assembly")

		return nil, nil

}

//Update Assembly based on Id (Now only status)
func (t *TnT) updateAssemblyByID(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2.")
	}

		_assemblyId := args[0]
		//_deviceSerialNo:= args[1]
		//_deviceType:=args[2]
		//_FilamentBatchId:=args[3]
		//_LedBatchId:=args[4]
		//_CircuitBoardBatchId:=args[5]
		//_WireBatchId:=args[6]
		//_CasingBatchId:=args[7]
		//_AdaptorBatchId:=args[8]
		//_StickPodBatchId:=args[9]
		//_ManufacturingPlant:=args[10]
		_AssemblyStatus:= args[1]
		//_AssemblyCreationDate := args[12]
		//_AssemblyCreatedBy :=  args[13]
		_time:= time.Now().Local()
		_AssemblyLastUpdateOn := _time.Format("2006-01-02")
		//_AssemblyLastUpdatedBy := ""

		//check if marble already exists
		assemblyAsBytes, err := stub.GetState(_assemblyId)
		if err != nil {
		return nil, errors.New("Failed to get assembly Id")
		}
		res := AssemblyLine{}
		json.Unmarshal(assemblyAsBytes, &res)

		//update the AssemblyLine status
		res.AssemblyStatus = _AssemblyStatus
		res.AssemblyLastUpdatedOn = _AssemblyLastUpdateOn

		//str := `{ "assemblyStatus": "` + _AssemblyStatus + `", "assemblyLastUpdateOn": "` +  _AssemblyLastUpdateOn  + `"}`
		//err := stub.PutState(_assemblyId, []byte(str))
		//write the status into the chaincode state

		bytes, err := json.Marshal(res)

		if err != nil { fmt.Printf("SAVE_CHANGES: Error converting Assembly record: %s", err); return nil, errors.New("Error converting Assembly record") }

		err = stub.PutState(_assemblyId, bytes)

		if err != nil { fmt.Printf("SAVE_CHANGES: Error storing Assembly record: %s", err); return nil, errors.New("Error storing Assembly record") }

		return nil, nil

		//return nil, nil

}

//get the Assembly against ID
func (t *TnT) getAssemblyByID(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting AssemblyID to query")
	}

	_assemblyId := args[0]

	valAsbytes, err := stub.GetState(_assemblyId)									//get the var from chaincode state
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " +  _assemblyId  + "\"}"
		return nil, errors.New(jsonResp)
	}

	return valAsbytes, nil

}

// Invoke callback representing the invocation of a chaincode
func (t *TnT) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Printf("Invoke called, determining function")

	// Handle different functions
	if function == "init" {
		fmt.Printf("Function is init")
		return t.Init(stub, function, args)
	} else if function == "createAssembly" {
		fmt.Printf("Function is createAssembly")
		return t.createAssembly(stub, args)
	} else if function == "updateAssemblyByID" {
		fmt.Printf("Function is updateAssemblyByID")
		return t.updateAssemblyByID(stub, args)
	}
	return nil, errors.New("Received unknown function invocation")
}

// query queries the chaincode
func (t *TnT) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Printf("Query called, determining function")

	if function == "getAssemblyByID" {
		t := TnT{}
		return t.getAssemblyByID(stub, args)
	}

	return nil, errors.New("Received unknown function query")
}

	func main() {
	err := shim.Start(new(TnT))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}
<|endoftext|>