<commit_before>// Copyright 2015 CodeIgnition. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// Package config provides utilities for dealing
// with configuration files for recond.
package config

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"sync"

	"github.com/codeignition/recon/internal/fileutil"
	"github.com/codeignition/recon/policy"
)

const configFileName = ".recond.json"

// config file path in the local machine
var configPath string

func init() {
	usr, err := user.Current()
	if err != nil {
		log.Fatalln(err)
	}
	configPath = filepath.Join(usr.HomeDir, configFileName)
}

// Config represents the configuration for the recond
// running on a particular machine.
type Config struct {
	sync.Mutex
	UID          string // Unique Identifier to register with marksman
	PolicyConfig policy.Config
}

// Init initializes and returns a Config. i.e. if the config file doesn't exist,
// it generates an new UID, creates the config file and returns the corresponding Config.
func Init() (*Config, error) {
	if fileutil.Exists(configPath) {
		f, err := os.Open(configPath)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		return parseConfig(f)
	}
	uid, err := generateUID()
	if err != nil {
		return nil, err
	}
	c := &Config{
		UID: uid,
	}
	err = c.Save()
	return c, err
}

// Save saves the config in a configuration file.
// If it already exists, it removes it and writes it freshly.
func (c *Config) Save() error {
	defer c.Unlock()
	c.Lock()
	if fileutil.Exists(configPath) {
		if err := os.Remove(configPath); err != nil {
			return err
		}
	}

	f, err := os.Create(configPath)
	if err != nil {
		return err
	}
	// Brad Fitzpatrick:
	// Never defer a file Close when the file was opened for writing.
	// Many filesystems do their real work (and thus their real failures) on close.
	// You can defer a file.Close for Read, but not for write.

	var out bytes.Buffer
	b, err := json.MarshalIndent(c, "", "  ")
	if err != nil {
		return err
	}
	out.Write(b)
	out.WriteTo(f)

	if err := f.Close(); err != nil {
		return err
	}

	return nil
}

func (c *Config) AddPolicy(p policy.Policy) error {
	defer c.Unlock()
	c.Lock()
	for _, k := range c.PolicyConfig {
		if k.Name == p.Name {
			return errors.New("policy with the given name already exists")
		}
	}
	c.PolicyConfig = append(c.PolicyConfig, p)
	return nil
}

// parseConfig reads from a io.Reader and
// creates a Config struct accordingly.
// It takes an io.Reader so that it is easier
// to test it.
func parseConfig(r io.Reader) (*Config, error) {
	dec := json.NewDecoder(r)
	var c Config
	if err := dec.Decode(&c); err != nil {
		return nil, err
	}
	return &c, nil
}

// generateUID returns a UID string of length 12.
func generateUID() (string, error) {
	b := make([]byte, 6)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}

	// b is of 6 bytes length, but when converted into base-16,
	// uid has a length of 12
	uid := fmt.Sprintf("%x", b)
	return uid, nil
}
<commit_msg>config: don't lock and unlock the config inside Save<commit_after>// Copyright 2015 CodeIgnition. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

// Package config provides utilities for dealing
// with configuration files for recond.
package config

import (
	"bytes"
	"crypto/rand"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"sync"

	"github.com/codeignition/recon/internal/fileutil"
	"github.com/codeignition/recon/policy"
)

const configFileName = ".recond.json"

// config file path in the local machine
var configPath string

func init() {
	usr, err := user.Current()
	if err != nil {
		log.Fatalln(err)
	}
	configPath = filepath.Join(usr.HomeDir, configFileName)
}

// Config represents the configuration for the recond
// running on a particular machine.
type Config struct {
	sync.Mutex
	UID          string // Unique Identifier to register with marksman
	PolicyConfig policy.Config
}

// Init initializes and returns a Config. i.e. if the config file doesn't exist,
// it generates an new UID, creates the config file and returns the corresponding Config.
func Init() (*Config, error) {
	if fileutil.Exists(configPath) {
		f, err := os.Open(configPath)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		return parseConfig(f)
	}
	uid, err := generateUID()
	if err != nil {
		return nil, err
	}
	c := &Config{
		UID: uid,
	}
	err = c.Save()
	return c, err
}

// Save saves the config in a configuration file.
// If it already exists, it removes it and writes it freshly.
// Make sure you lock and unlock the config while calling Save.
func (c *Config) Save() error {
	if fileutil.Exists(configPath) {
		if err := os.Remove(configPath); err != nil {
			return err
		}
	}

	f, err := os.Create(configPath)
	if err != nil {
		return err
	}
	// Brad Fitzpatrick:
	// Never defer a file Close when the file was opened for writing.
	// Many filesystems do their real work (and thus their real failures) on close.
	// You can defer a file.Close for Read, but not for write.

	var out bytes.Buffer
	b, err := json.MarshalIndent(c, "", "  ")
	if err != nil {
		return err
	}
	out.Write(b)
	out.WriteTo(f)

	if err := f.Close(); err != nil {
		return err
	}

	return nil
}

func (c *Config) AddPolicy(p policy.Policy) error {
	defer c.Unlock()
	c.Lock()
	for _, k := range c.PolicyConfig {
		if k.Name == p.Name {
			return errors.New("policy with the given name already exists")
		}
	}
	c.PolicyConfig = append(c.PolicyConfig, p)
	return nil
}

// parseConfig reads from a io.Reader and
// creates a Config struct accordingly.
// It takes an io.Reader so that it is easier
// to test it.
func parseConfig(r io.Reader) (*Config, error) {
	dec := json.NewDecoder(r)
	var c Config
	if err := dec.Decode(&c); err != nil {
		return nil, err
	}
	return &c, nil
}

// generateUID returns a UID string of length 12.
func generateUID() (string, error) {
	b := make([]byte, 6)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}

	// b is of 6 bytes length, but when converted into base-16,
	// uid has a length of 12
	uid := fmt.Sprintf("%x", b)
	return uid, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"text/tabwriter"
	"time"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/registry"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	d "github.com/mobingilabs/mobingi-sdk-go/pkg/debug"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/pretty"
	"github.com/spf13/cobra"
)

func DescribeImageCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "describe",
		Short: "describe an image",
		Long: `Describe an image.

Example:

  $ ` + cmdline.Args0() + ` registry descrube --image foo`,
		Run: describeImage,
	}

	cmd.Flags().SortFlags = false
	cmd.Flags().String("username", "", "username (account subuser)")
	cmd.Flags().String("password", "", "password (account subuser)")
	cmd.Flags().String("image", "", "image name")
	return cmd
}

func describeImage(cmd *cobra.Command, args []string) {
	sess, err := clisession()
	d.ErrorExit(err, 1)

	ensureUserPass(cmd, sess)
	svc := registry.New(sess)
	in := &registry.DescribeImageInput{
		Image: cli.GetCliStringFlag(cmd, "image"),
	}

	resp, body, err := svc.DescribeImage(in)
	d.ErrorExit(err, 1)
	exitOn401(resp)

	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, body, 0644)
			d.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		js := pretty.JSON(string(body), indent)
		fmt.Println(js)

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, []byte(js), 0644)
			d.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	default:
		w := tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
		fmt.Fprintf(w, "REPO\tSIZE\tCREATED\tVISIBILITY\tTAGS\n")
		var repos []json.RawMessage
		err = json.Unmarshal(body, &repos)
		d.ErrorExit(err, 1)

		for _, item := range repos {
			var m map[string]interface{}
			err = json.Unmarshal(item, &m)
			d.ErrorExit(err, 1)

			var repo, size, created, vis, tags string
			if _, ok := m["repository"]; ok {
				repo = fmt.Sprintf("%s", m["repository"])
			}

			if _, ok := m["size"]; ok {
				size = fmt.Sprintf("%v", m["size"])
			}

			if _, ok := m["created_at"]; ok {
				created = fmt.Sprintf("%v", m["created_at"])
				t, err := time.Parse(time.RFC3339, created)
				if err == nil {
					created = t.Format(time.RFC1123)
				}
			}

			if _, ok := m["visibility"]; ok {
				vis = fmt.Sprintf("%v", m["visibility"])
			}

			// count tags
			if _, ok := m["tags"]; ok {
				var t1 map[string]json.RawMessage
				err = json.Unmarshal(item, &t1)
				if err == nil {
					if t2, ok := t1["tags"]; ok {
						var cnt map[string]interface{}
						err = json.Unmarshal(t2, &cnt)
						if err == nil {
							tags = fmt.Sprintf("%v", len(cnt))
						}
					}
				}
			}

			fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
				repo,
				size,
				created,
				vis,
				tags)
		}

		/*
			for i, s := range stacks {
				timestr := s.CreateTime
				t, err := time.Parse(time.RFC3339, s.CreateTime)
				if err == nil {
					timestr = t.Format(time.RFC1123)
				}

				platform := "?"
				if s.Configuration.AWS != "" {
					platform = "AWS"
				}

				type cnf_t struct {
					Configuration json.RawMessage `json:"configuration"`
				}

				// if still invalid, find via regexp
				if platform == "?" {
					var cnfs []cnf_t
					err = json.Unmarshal(body, &cnfs)
					if err == nil {
						re := regexp.MustCompile(`"vendor":\{"aws":`)
						pltfm := re.FindString(string(cnfs[i].Configuration))
						if pltfm != "" {
							platform = "AWS"
						}
					}
				}

				region := s.Configuration.Region

				// if empty, extract the `"region:"xxxxxx"` part via regexp
				if region == "" {
					var cnfs []cnf_t
					err = json.Unmarshal(body, &cnfs)
					if err == nil {
						re := regexp.MustCompile(`"region":\s*".+"`)
						mi := pretty.JSON(cnfs[i].Configuration, 2)
						if mi != "" {
							rgn := re.FindString(mi)
							rgnkv := strings.Split(rgn, ":")
							if len(rgnkv) == 2 {
								r1 := strings.TrimSpace(rgnkv[1])
								region = strings.TrimRight(strings.TrimPrefix(r1, "\""), "\"")
							}
						}
					}
				}

				fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
					s.StackId,
					s.Nickname,
					platform,
					s.StackStatus,
					region,
					timestr)
			}
		*/

		w.Flush()
	}
}
<commit_msg>Cleanup code.<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"text/tabwriter"
	"time"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/registry"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	d "github.com/mobingilabs/mobingi-sdk-go/pkg/debug"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/pretty"
	"github.com/spf13/cobra"
)

func DescribeImageCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "describe",
		Short: "describe an image",
		Long: `Describe an image.

Example:

  $ ` + cmdline.Args0() + ` registry descrube --image foo`,
		Run: describeImage,
	}

	cmd.Flags().SortFlags = false
	cmd.Flags().String("username", "", "username (account subuser)")
	cmd.Flags().String("password", "", "password (account subuser)")
	cmd.Flags().String("image", "", "image name")
	return cmd
}

func describeImage(cmd *cobra.Command, args []string) {
	sess, err := clisession()
	d.ErrorExit(err, 1)

	ensureUserPass(cmd, sess)
	svc := registry.New(sess)
	in := &registry.DescribeImageInput{
		Image: cli.GetCliStringFlag(cmd, "image"),
	}

	resp, body, err := svc.DescribeImage(in)
	d.ErrorExit(err, 1)
	exitOn401(resp)

	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, body, 0644)
			d.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		js := pretty.JSON(string(body), indent)
		fmt.Println(js)

		// write to file option
		f := cli.GetCliStringFlag(cmd, "out")
		if f != "" {
			err = ioutil.WriteFile(f, []byte(js), 0644)
			d.ErrorExit(err, 1)
			d.Info(fmt.Sprintf("Output written to %s.", f))
		}
	default:
		w := tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
		fmt.Fprintf(w, "REPO\tSIZE\tCREATED\tVISIBILITY\tTAGS\n")
		var repos []json.RawMessage
		err = json.Unmarshal(body, &repos)
		d.ErrorExit(err, 1)

		for _, item := range repos {
			var m map[string]interface{}
			err = json.Unmarshal(item, &m)
			d.ErrorExit(err, 1)

			var repo, size, created, vis, tags string
			if _, ok := m["repository"]; ok {
				repo = fmt.Sprintf("%s", m["repository"])
			}

			if _, ok := m["size"]; ok {
				size = fmt.Sprintf("%v", m["size"])
			}

			if _, ok := m["created_at"]; ok {
				created = fmt.Sprintf("%v", m["created_at"])
				t, err := time.Parse(time.RFC3339, created)
				if err == nil {
					created = t.Format(time.RFC1123)
				}
			}

			if _, ok := m["visibility"]; ok {
				vis = fmt.Sprintf("%v", m["visibility"])
			}

			// count tags
			if _, ok := m["tags"]; ok {
				var t1 map[string]json.RawMessage
				err = json.Unmarshal(item, &t1)
				if err == nil {
					if t2, ok := t1["tags"]; ok {
						var cnt map[string]interface{}
						err = json.Unmarshal(t2, &cnt)
						if err == nil {
							tags = fmt.Sprintf("%v", len(cnt))
						}
					}
				}
			}

			fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
				repo,
				size,
				created,
				vis,
				tags)
		}

		w.Flush()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/kkdai/youtube/v2"
	ytdl "github.com/kkdai/youtube/v2/downloader"
	"github.com/spf13/pflag"
	"golang.org/x/net/http/httpproxy"
)

var (
	insecureSkipVerify bool   // skip TLS server validation
	outputQuality      string // itag number or quality string
	mimetype           string // mimetype
	downloader         *ytdl.Downloader
)

func addQualityFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&outputQuality, "quality", "q", "", "The itag number or quality label (hd720, medium)")
}

func addMimeTypeFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&mimetype, "mimetype", "m", "mp4", "Mime-Type to filter (mp4, webm, av01, avc1) - applicable if --quality used is quality label")
}

func getDownloader() *ytdl.Downloader {
	if downloader != nil {
		return downloader
	}

	proxyFunc := httpproxy.FromEnvironment().ProxyFunc()
	httpTransport := &http.Transport{
		// Proxy: http.ProxyFromEnvironment() does not work. Why?
		Proxy: func(r *http.Request) (uri *url.URL, err error) {
			return proxyFunc(r.URL)
		},
		IdleConnTimeout:       60 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		ForceAttemptHTTP2:     true,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
	}

	if insecureSkipVerify {
		log.Println("Skip server certificate verification")
		httpTransport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	downloader = &ytdl.Downloader{
		OutputDir: outputDir,
	}
	downloader.Client.Debug = verbose
	downloader.HTTPClient = &http.Client{Transport: httpTransport}

	return downloader
}

func getVideoWithFormat(id string) (*youtube.Video, *youtube.Format, error) {
	dl := getDownloader()
	video, err := dl.GetVideo(id)
	if err != nil {
		return nil, nil, err
	}
	formats := video.Formats

	var format *youtube.Format
	itag, _ := strconv.Atoi(outputQuality)
	switch {
	case itag > 0:
		format = formats.FindByItag(itag)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with itag %d", itag)
		}

	case outputQuality != "":
		if mimetype != "" {
			formats = formats.Type(mimetype)
		}
		if len(formats) == 0 {
			return nil, nil, errors.New("no formats found")
		}
		format = formats.FindByQuality(outputQuality)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with quality %s", outputQuality)
		}

	default:
		if mimetype != "" {
			formats = formats.Type(mimetype)
		}
		if len(formats) == 0 {
			return nil, nil, errors.New("no formats found")
		}
		// select the first format
		formats.Sort()
		format = &formats[0]
	}

	return video, format, nil
}
<commit_msg>refactor to avoid duplicate code<commit_after>package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/kkdai/youtube/v2"
	ytdl "github.com/kkdai/youtube/v2/downloader"
	"github.com/spf13/pflag"
	"golang.org/x/net/http/httpproxy"
)

var (
	insecureSkipVerify bool   // skip TLS server validation
	outputQuality      string // itag number or quality string
	mimetype           string // mimetype
	downloader         *ytdl.Downloader
)

func addQualityFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&outputQuality, "quality", "q", "", "The itag number or quality label (hd720, medium)")
}

func addMimeTypeFlag(flagSet *pflag.FlagSet) {
	flagSet.StringVarP(&mimetype, "mimetype", "m", "mp4", "Mime-Type to filter (mp4, webm, av01, avc1) - applicable if --quality used is quality label")
}

func getDownloader() *ytdl.Downloader {
	if downloader != nil {
		return downloader
	}

	proxyFunc := httpproxy.FromEnvironment().ProxyFunc()
	httpTransport := &http.Transport{
		// Proxy: http.ProxyFromEnvironment() does not work. Why?
		Proxy: func(r *http.Request) (uri *url.URL, err error) {
			return proxyFunc(r.URL)
		},
		IdleConnTimeout:       60 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
		ForceAttemptHTTP2:     true,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
	}

	if insecureSkipVerify {
		log.Println("Skip server certificate verification")
		httpTransport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}

	downloader = &ytdl.Downloader{
		OutputDir: outputDir,
	}
	downloader.Client.Debug = verbose
	downloader.HTTPClient = &http.Client{Transport: httpTransport}

	return downloader
}

func getVideoWithFormat(id string) (*youtube.Video, *youtube.Format, error) {
	dl := getDownloader()
	video, err := dl.GetVideo(id)
	if err != nil {
		return nil, nil, err
	}
	formats := video.Formats
	if mimetype != "" {
		formats = formats.Type(mimetype)
	}
	if len(formats) == 0 {
		return nil, nil, errors.New("no formats found")
	}

	var format *youtube.Format
	itag, _ := strconv.Atoi(outputQuality)
	switch {
	case itag > 0:
		// When an itag is specified, do not filter format with mime-type
		format = video.Formats.FindByItag(itag)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with itag %d", itag)
		}

	case outputQuality != "":
		format = formats.FindByQuality(outputQuality)
		if format == nil {
			return nil, nil, fmt.Errorf("unable to find format with quality %s", outputQuality)
		}

	default:
		// select the first format
		formats.Sort()
		format = &formats[0]
	}

	return video, format, nil
}
<|endoftext|>


<commit_before>//
// A command line utility designed to take a XML based Excel file
// and turn each row into a JSON blob. The JSON blob returned for
// each row can be processed via a JavaScript callback allowing for
// flexible translations for spreadsheet to JSON output.
//
// @author R. S. Doiel, <rsdoiel@gmail.com>
// copyright (c) 2016
//
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"

	"github.com/robertkrimen/otto"
	"github.com/tealeg/xlsx"
)

var (
	help          bool
	asArray       bool
	inputFilename *string
	jsFilename    *string
	jsCallback    *string
)

type jsResponse struct {
	Path   string                 `json:"path"`
	Source map[string]interface{} `json:"source"`
	Error  string                 `json:"error"`
}

func usage() {
	fmt.Println(`

 USAGE: xlsx2json [OPTIONS] EXCEL_FILENAME

 OVERVIEW

 Read a .xlsx file and return each row as a JSON object (or array of objects).
 If a JavaScript file and callback name are provided then that will be used to
 generate the resulting JSON object per row.

 JAVASCRIPT

 The callback function in JavaScript should return an object that looks like

     {"path": ..., "source": ..., "error": ...}

 The "path" property should contain the desired filename to use for storing
 the JSON blob. If it is empty the output will only be displayed to standard out.

 The "source" property should be the final version of the object you want to
 turn into a JSON blob.

 The "error" property is a string and if the string is not empty it will be
 used as an error message and cause the processing to stop.

 A simple JavaScript Examples:

    // Counter i is used to name the JSON output files.
    var i = 0;

    // callback is the default name looked for when processing.
    // the command line option -callback lets you used a different name.
    function callback(row) {
        i += 1;
        if (i > 10) {
            // Stop if processing more than 10 rows.
            return {"error": "too many rows..."}
        }
        return {
            "path": "data/" + i + ".json",
            "source": row,
            "error": ""
        }
    }

 OPTIONS
`)
	flag.PrintDefaults()
	fmt.Println(`

 Examples

    xlsx2json -as-array myfile.xlsx

    xlsx2json -js row2obj.js -callback row2obj myfile.xlsx

`)
	os.Exit(0)
}

func init() {
	flag.BoolVar(&help, "h", false, "display this help message")
	flag.BoolVar(&help, "help", false, "display this help message")
	flag.BoolVar(&asArray, "as-array", false, "Write the JSON blobs output as an array")
	inputFilename = flag.String("i", "", "Read the Excel file from this name")
	jsFilename = flag.String("js", "", "The name of the JavaScript file containing callback function")
	jsCallback = flag.String("callback", "callback", "The name of the JavaScript function to use as a callback")
}

func main() {
	var (
		xlFile   *xlsx.File
		vm       *otto.Otto
		jsSource []byte
		jsScript *otto.Script
	)
	flag.Parse()

	if help == true {
		usage()
	}

	args := flag.Args()
	if len(args) > 0 {
		*inputFilename = args[0]
	}
	if *inputFilename == "" {
		// Read Excel file from standard
		log.Fatalf("Need to provide an xlsx file for input, -i")
	}
	// Read from the given file path
	xlFile, err := xlsx.OpenFile(*inputFilename)
	if err != nil {
		log.Fatalf("Can't open %s, %s", *inputFilename, err)
	}
	jsMap := false
	if *jsFilename != "" {
		fname := fmt.Sprintf("%s", *jsFilename)
		jsSource, err = ioutil.ReadFile(fname)
		if err != nil {
			log.Fatalf("Can't read JavaScript file %s, %s", fname, err)
		}
		vm = otto.New()
		jsMap = true
        vm.Set("Getenv", func(call otto.FunctionCall) otto.Value {
                envvar := call.Argument(0).String()
                result, err := vm.ToValue(os.Getenv(envvar))
                if err != nil {
                        log.Fatalf("Getenv(%q) error, %s", envvar, err)
                }
                return result
        })
        vm.Set("HttpGet", func(call otto.FunctionCall) otto.Value {
                uri := call.Argument(0).String()
                resp, err := http.Get(uri)
                if err != nil {
                        log.Fatalf("Can't connect to %s, %s", uri, err)
                }
                defer resp.Body.Close()
                content, err := ioutil.ReadAll(resp.Body)
                if err != nil {
                        log.Fatalf("Can't read response %s, %s", uri, err)
                }
                result, err := vm.ToValue(fmt.Sprintf("%s", content))
                if err != nil {
                        log.Fatalf("HttpGet(%q) error, %s", uri, err)
                }
                return result
        })
        vm.Set("HttpPost", func(call otto.FunctionCall) otto.Value {
                uri := call.Argument(0).String()
                mimeType := call.Argument(1).String()
                payload := call.Argument(2).String()
                buf := strings.NewReader(payload)

                resp, err := http.Post(uri, mimeType, buf)
                if err != nil {
                        log.Fatalf("Can't connect to %s, %s", uri, err)
                }
                defer resp.Body.Close()
                content, err := ioutil.ReadAll(resp.Body)
                if err != nil {
                        log.Fatalf("Can't read response %s, %s", uri, err)
                }
                result, err := vm.ToValue(fmt.Sprintf("%s", content))
                if err != nil {
                        log.Fatalf("HttpGet(%q) error, %s", uri, err)
                }
                return result
        })

		jsScript, err = vm.Compile(*jsFilename, jsSource)
		if err != nil {
			log.Fatalf("Can't compile %s, %s", *jsFilename, err)
		}
		//FIXME: add JS wrapped Golang packages
		// Define any functions, will evaluate each row with vm.Eval()
		vm.Run(jsScript)
	}

	for _, sheet := range xlFile.Sheets {
		columnNames := []string{}
		if asArray == true {
			fmt.Println("[")
		}
		for rowNo, row := range sheet.Rows {
			if asArray == true && rowNo > 1 {
				fmt.Printf(", ")
			}
			jsonBlob := map[string]string{}
			for colNo, cell := range row.Cells {
				if rowNo == 0 {
					columnNames = append(columnNames, cell.String())
				} else {
					// Build a map and render it out
					if colNo < len(columnNames) {
						jsonBlob[columnNames[colNo]] = cell.String()
					} else {
						k := fmt.Sprintf("column_%d", colNo+1)
						columnNames = append(columnNames, k)
						jsonBlob[k] = cell.String()
					}
				}
			}
			if rowNo > 0 {
				src, err := json.Marshal(jsonBlob)
				if err != nil {
					log.Fatalf("Can't render JSON blob, %s", err)
				}
				if jsMap == true {
					// We're eval the callback from inside a closure to be safer
					js := fmt.Sprintf("(function(){ return %s(%s);}())", *jsCallback, src)
					jsValue, err := vm.Eval(js)
					if err != nil {
						log.Fatalf("row: %d, Can't run %s, %s", rowNo, *jsFilename, err)
					}
					val, err := jsValue.Export()
					if err != nil {
						log.Fatalf("row: %d, Can't convert JavaScript value %s(%s), %s", rowNo, *jsCallback, src, err)
					}
					src, err = json.Marshal(val)
					if err != nil {
						log.Fatalf("row: %d, src: %s\njs returned %v\nerror: %s", rowNo, js, jsValue, err)
					}
					response := new(jsResponse)
					err = json.Unmarshal(src, &response)
					if err != nil {
						log.Fatalf("row: %d, do not understand response %s, %s", rowNo, src, err)
					}
					if response.Error != "" {
						log.Fatalf("row: %d, %s", rowNo, response.Error)
					}
					// Now re-package response.Source into a JSON blob
					src, err = json.Marshal(response.Source)
					if err != nil {
						log.Fatalf("row: %d, %s", rowNo, err)
					}
					if response.Path != "" {
						d := path.Dir(response.Path)
						if d != "." {
							os.MkdirAll(d, 0775)
						}
						ioutil.WriteFile(response.Path, src, 0664)
					}
				}
				fmt.Printf("%s\n", src)
			}
		}
		if asArray == true {
			fmt.Println("]")
		}

	}
}
<commit_msg>fixed missing imports<commit_after>//
// A command line utility designed to take a XML based Excel file
// and turn each row into a JSON blob. The JSON blob returned for
// each row can be processed via a JavaScript callback allowing for
// flexible translations for spreadsheet to JSON output.
//
// @author R. S. Doiel, <rsdoiel@gmail.com>
// copyright (c) 2016
//
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"strings"

	"github.com/robertkrimen/otto"
	"github.com/tealeg/xlsx"
)

var (
	help          bool
	asArray       bool
	inputFilename *string
	jsFilename    *string
	jsCallback    *string
)

type jsResponse struct {
	Path   string                 `json:"path"`
	Source map[string]interface{} `json:"source"`
	Error  string                 `json:"error"`
}

func usage() {
	fmt.Println(`

 USAGE: xlsx2json [OPTIONS] EXCEL_FILENAME

 OVERVIEW

 Read a .xlsx file and return each row as a JSON object (or array of objects).
 If a JavaScript file and callback name are provided then that will be used to
 generate the resulting JSON object per row.

 JAVASCRIPT

 The callback function in JavaScript should return an object that looks like

     {"path": ..., "source": ..., "error": ...}

 The "path" property should contain the desired filename to use for storing
 the JSON blob. If it is empty the output will only be displayed to standard out.

 The "source" property should be the final version of the object you want to
 turn into a JSON blob.

 The "error" property is a string and if the string is not empty it will be
 used as an error message and cause the processing to stop.

 A simple JavaScript Examples:

    // Counter i is used to name the JSON output files.
    var i = 0;

    // callback is the default name looked for when processing.
    // the command line option -callback lets you used a different name.
    function callback(row) {
        i += 1;
        if (i > 10) {
            // Stop if processing more than 10 rows.
            return {"error": "too many rows..."}
        }
        return {
            "path": "data/" + i + ".json",
            "source": row,
            "error": ""
        }
    }

 OPTIONS
`)
	flag.PrintDefaults()
	fmt.Println(`

 Examples

    xlsx2json -as-array myfile.xlsx

    xlsx2json -js row2obj.js -callback row2obj myfile.xlsx

`)
	os.Exit(0)
}

func init() {
	flag.BoolVar(&help, "h", false, "display this help message")
	flag.BoolVar(&help, "help", false, "display this help message")
	flag.BoolVar(&asArray, "as-array", false, "Write the JSON blobs output as an array")
	inputFilename = flag.String("i", "", "Read the Excel file from this name")
	jsFilename = flag.String("js", "", "The name of the JavaScript file containing callback function")
	jsCallback = flag.String("callback", "callback", "The name of the JavaScript function to use as a callback")
}

func main() {
	var (
		xlFile   *xlsx.File
		vm       *otto.Otto
		jsSource []byte
		jsScript *otto.Script
	)
	flag.Parse()

	if help == true {
		usage()
	}

	args := flag.Args()
	if len(args) > 0 {
		*inputFilename = args[0]
	}
	if *inputFilename == "" {
		// Read Excel file from standard
		log.Fatalf("Need to provide an xlsx file for input, -i")
	}
	// Read from the given file path
	xlFile, err := xlsx.OpenFile(*inputFilename)
	if err != nil {
		log.Fatalf("Can't open %s, %s", *inputFilename, err)
	}
	jsMap := false
	if *jsFilename != "" {
		fname := fmt.Sprintf("%s", *jsFilename)
		jsSource, err = ioutil.ReadFile(fname)
		if err != nil {
			log.Fatalf("Can't read JavaScript file %s, %s", fname, err)
		}
		vm = otto.New()
		jsMap = true
		vm.Set("Getenv", func(call otto.FunctionCall) otto.Value {
			envvar := call.Argument(0).String()
			result, err := vm.ToValue(os.Getenv(envvar))
			if err != nil {
				log.Fatalf("Getenv(%q) error, %s", envvar, err)
			}
			return result
		})
		vm.Set("HttpGet", func(call otto.FunctionCall) otto.Value {
			uri := call.Argument(0).String()
			resp, err := http.Get(uri)
			if err != nil {
				log.Fatalf("Can't connect to %s, %s", uri, err)
			}
			defer resp.Body.Close()
			content, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				log.Fatalf("Can't read response %s, %s", uri, err)
			}
			result, err := vm.ToValue(fmt.Sprintf("%s", content))
			if err != nil {
				log.Fatalf("HttpGet(%q) error, %s", uri, err)
			}
			return result
		})
		vm.Set("HttpPost", func(call otto.FunctionCall) otto.Value {
			uri := call.Argument(0).String()
			mimeType := call.Argument(1).String()
			payload := call.Argument(2).String()
			buf := strings.NewReader(payload)

			resp, err := http.Post(uri, mimeType, buf)
			if err != nil {
				log.Fatalf("Can't connect to %s, %s", uri, err)
			}
			defer resp.Body.Close()
			content, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				log.Fatalf("Can't read response %s, %s", uri, err)
			}
			result, err := vm.ToValue(fmt.Sprintf("%s", content))
			if err != nil {
				log.Fatalf("HttpGet(%q) error, %s", uri, err)
			}
			return result
		})

		jsScript, err = vm.Compile(*jsFilename, jsSource)
		if err != nil {
			log.Fatalf("Can't compile %s, %s", *jsFilename, err)
		}
		//FIXME: add JS wrapped Golang packages
		// Define any functions, will evaluate each row with vm.Eval()
		vm.Run(jsScript)
	}

	for _, sheet := range xlFile.Sheets {
		columnNames := []string{}
		if asArray == true {
			fmt.Println("[")
		}
		for rowNo, row := range sheet.Rows {
			if asArray == true && rowNo > 1 {
				fmt.Printf(", ")
			}
			jsonBlob := map[string]string{}
			for colNo, cell := range row.Cells {
				if rowNo == 0 {
					columnNames = append(columnNames, cell.String())
				} else {
					// Build a map and render it out
					if colNo < len(columnNames) {
						jsonBlob[columnNames[colNo]] = cell.String()
					} else {
						k := fmt.Sprintf("column_%d", colNo+1)
						columnNames = append(columnNames, k)
						jsonBlob[k] = cell.String()
					}
				}
			}
			if rowNo > 0 {
				src, err := json.Marshal(jsonBlob)
				if err != nil {
					log.Fatalf("Can't render JSON blob, %s", err)
				}
				if jsMap == true {
					// We're eval the callback from inside a closure to be safer
					js := fmt.Sprintf("(function(){ return %s(%s);}())", *jsCallback, src)
					jsValue, err := vm.Eval(js)
					if err != nil {
						log.Fatalf("row: %d, Can't run %s, %s", rowNo, *jsFilename, err)
					}
					val, err := jsValue.Export()
					if err != nil {
						log.Fatalf("row: %d, Can't convert JavaScript value %s(%s), %s", rowNo, *jsCallback, src, err)
					}
					src, err = json.Marshal(val)
					if err != nil {
						log.Fatalf("row: %d, src: %s\njs returned %v\nerror: %s", rowNo, js, jsValue, err)
					}
					response := new(jsResponse)
					err = json.Unmarshal(src, &response)
					if err != nil {
						log.Fatalf("row: %d, do not understand response %s, %s", rowNo, src, err)
					}
					if response.Error != "" {
						log.Fatalf("row: %d, %s", rowNo, response.Error)
					}
					// Now re-package response.Source into a JSON blob
					src, err = json.Marshal(response.Source)
					if err != nil {
						log.Fatalf("row: %d, %s", rowNo, err)
					}
					if response.Path != "" {
						d := path.Dir(response.Path)
						if d != "." {
							os.MkdirAll(d, 0775)
						}
						ioutil.WriteFile(response.Path, src, 0664)
					}
				}
				fmt.Printf("%s\n", src)
			}
		}
		if asArray == true {
			fmt.Println("]")
		}

	}
}
<|endoftext|>


<commit_before>package Common

// +build cgo

/*
#include <time.h>
#include <stdlib.h>

int buildDate() {
	struct tm t;
	strptime(__DATE__, "%b %d %Y", &t);
	char buf[256] = {0};
	strftime(buf, sizeof(buf), "%Y%m%d", &t);
	return atoi(buf);
}

int buildTime() {
	struct tm t;
	strptime(__TIME__, "%H:%M:%S", &t);
	char buf[256] = {0};
	strftime(buf, sizeof(buf), "%H%M%S", &t);
	return atoi(buf);
}
*/
import "C"
import "flag"

func init() {
	flag.Uint64("--build--timestamp", BuildDateTime(), "build date-time, as a tag")
}

func BuildDateTime() uint64 {
	return uint64(C.buildDate())*1000000 + uint64(C.buildTime())
}
<commit_msg>remove build date<commit_after><|endoftext|>


<commit_before>package main

import (
	"github.com/mattn/go-runewidth"
	"github.com/zyedidia/tcell"
)

func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}

func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsize int) (int, int, *tcell.Style) {
	charPos := 0
	var lineIdx int
	var lastWidth int
	var style *tcell.Style
	var width int
	var rw int
	for i, c := range str {
		// width := StringWidth(str[:i], tabsize)

		if group, ok := buf.Match(lineN)[charPos]; ok {
			s := GetColor(group.String())
			style = &s
		}

		if width >= visualIndex {
			return charPos, visualIndex - lastWidth, style
		}

		if i != 0 {
			charPos++
			lineIdx += rw
		}
		lastWidth = width
		rw = 0
		if c == '\t' {
			rw = tabsize - (lineIdx % tabsize)
			width += rw
		} else {
			rw = runewidth.RuneWidth(c)
			width += rw
		}
	}

	return -1, -1, style
}

type Char struct {
	visualLoc Loc
	realLoc   Loc
	char      rune
	// The actual character that is drawn
	// This is only different from char if it's for example hidden character
	drawChar rune
	style    tcell.Style
	width    int
}

type CellView struct {
	lines [][]*Char
}

func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
	if width <= 0 {
		return
	}

	matchingBrace := Loc{-1, -1}
	// bracePairs is defined in buffer.go
	if buf.Settings["matchbrace"].(bool) {
		for _, bp := range bracePairs {
			if buf.Cursor.RuneUnder(buf.Cursor.X) == bp[0] {
				matchingBrace = buf.FindMatchingBrace(bp, buf.Cursor.Loc)
				break
			}
			left := buf.Cursor.Loc.X
			if buf.Settings["matchbraceleft"].(bool) {
				left -= 1
				if left < 0 {
					left = 0
				}
			}
			if buf.Cursor.RuneUnder(left) == bp[1] {
				matchingBrace = buf.FindMatchingBrace(
					bp, Loc{X: left, Y: buf.Cursor.Loc.Y})
			}
		}
	}

	tabsize := int(buf.Settings["tabsize"].(float64))
	softwrap := buf.Settings["softwrap"].(bool)
	indentrunes := []rune(buf.Settings["indentchar"].(string))
	// if empty indentchar settings, use space
	if indentrunes == nil || len(indentrunes) == 0 {
		indentrunes = []rune{' '}
	}
	indentchar := indentrunes[0]

	start := buf.Cursor.Y
	if buf.Settings["syntax"].(bool) && buf.syntaxDef != nil {
		if start > 0 && buf.lines[start-1].rehighlight {
			buf.highlighter.ReHighlightLine(buf, start-1)
			buf.lines[start-1].rehighlight = false
		}

		buf.highlighter.ReHighlightStates(buf, start)

		buf.highlighter.HighlightMatches(buf, top, top+height)
	}

	c.lines = make([][]*Char, 0)

	viewLine := 0
	lineN := top

	curStyle := defStyle
	for viewLine < height {
		if lineN >= len(buf.lines) {
			break
		}

		lineStr := buf.Line(lineN)
		line := []rune(lineStr)

		colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize)
		if colN < 0 {
			colN = len(line)
		}
		viewCol := -startOffset
		if startStyle != nil {
			curStyle = *startStyle
		}

		// We'll either draw the length of the line, or the width of the screen
		// whichever is smaller
		lineLength := min(StringWidth(lineStr, tabsize), width)
		c.lines = append(c.lines, make([]*Char, lineLength))

		wrap := false
		// We only need to wrap if the length of the line is greater than the width of the terminal screen
		if softwrap && StringWidth(lineStr, tabsize) > width {
			wrap = true
			// We're going to draw the entire line now
			lineLength = StringWidth(lineStr, tabsize)
		}

		for viewCol < lineLength {
			if colN >= len(line) {
				break
			}
			if group, ok := buf.Match(lineN)[colN]; ok {
				curStyle = GetColor(group.String())
			}

			char := line[colN]

			if viewCol >= 0 {
				st := curStyle
				if colN == matchingBrace.X && lineN == matchingBrace.Y && !buf.Cursor.HasSelection() {
					st = curStyle.Reverse(true)
				}
				if viewCol < len(c.lines[viewLine]) {
					c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, st, 1}
				}
			}
			if char == '\t' {
				charWidth := tabsize - (viewCol+left)%tabsize
				if viewCol >= 0 {
					c.lines[viewLine][viewCol].drawChar = indentchar
					c.lines[viewLine][viewCol].width = charWidth

					indentStyle := curStyle
					ch := buf.Settings["indentchar"].(string)
					if group, ok := colorscheme["indent-char"]; ok && !IsStrWhitespace(ch) && ch != "" {
						indentStyle = group
					}

					c.lines[viewLine][viewCol].style = indentStyle
				}

				for i := 1; i < charWidth; i++ {
					viewCol++
					if viewCol >= 0 && viewCol < lineLength && viewCol < len(c.lines[viewLine]) {
						c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
					}
				}
				viewCol++
			} else if runewidth.RuneWidth(char) > 1 {
				charWidth := runewidth.RuneWidth(char)
				if viewCol >= 0 {
					c.lines[viewLine][viewCol].width = charWidth
				}
				for i := 1; i < charWidth; i++ {
					viewCol++
					if viewCol >= 0 && viewCol < lineLength && viewCol < len(c.lines[viewLine]) {
						c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
					}
				}
				viewCol++
			} else {
				viewCol++
			}
			colN++

			if wrap && viewCol >= width {
				viewLine++

				// If we go too far soft wrapping we have to cut off
				if viewLine >= height {
					break
				}

				nextLine := line[colN:]
				lineLength := min(StringWidth(string(nextLine), tabsize), width)
				c.lines = append(c.lines, make([]*Char, lineLength))

				viewCol = 0
			}

		}
		if group, ok := buf.Match(lineN)[len(line)]; ok {
			curStyle = GetColor(group.String())
		}

		// newline
		viewLine++
		lineN++
	}

	for i := top; i < top+height; i++ {
		if i >= buf.NumLines {
			break
		}
		buf.SetMatch(i, nil)
	}
}
<commit_msg>Fix matchbraceleft option<commit_after>package main

import (
	"github.com/mattn/go-runewidth"
	"github.com/zyedidia/tcell"
)

func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}

func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsize int) (int, int, *tcell.Style) {
	charPos := 0
	var lineIdx int
	var lastWidth int
	var style *tcell.Style
	var width int
	var rw int
	for i, c := range str {
		// width := StringWidth(str[:i], tabsize)

		if group, ok := buf.Match(lineN)[charPos]; ok {
			s := GetColor(group.String())
			style = &s
		}

		if width >= visualIndex {
			return charPos, visualIndex - lastWidth, style
		}

		if i != 0 {
			charPos++
			lineIdx += rw
		}
		lastWidth = width
		rw = 0
		if c == '\t' {
			rw = tabsize - (lineIdx % tabsize)
			width += rw
		} else {
			rw = runewidth.RuneWidth(c)
			width += rw
		}
	}

	return -1, -1, style
}

type Char struct {
	visualLoc Loc
	realLoc   Loc
	char      rune
	// The actual character that is drawn
	// This is only different from char if it's for example hidden character
	drawChar rune
	style    tcell.Style
	width    int
}

type CellView struct {
	lines [][]*Char
}

func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
	if width <= 0 {
		return
	}

	matchingBrace := Loc{-1, -1}
	// bracePairs is defined in buffer.go
	if buf.Settings["matchbrace"].(bool) {
		for _, bp := range bracePairs {
			curX := buf.Cursor.X
			curLoc := buf.Cursor.Loc
			if buf.Settings["matchbraceleft"].(bool) {
				curX--
				if curX > 0 {
					curLoc = curLoc.Move(-1, buf)
				}
			}

			r := buf.Cursor.RuneUnder(curX)
			if r == bp[0] || r == bp[1] {
				matchingBrace = buf.FindMatchingBrace(bp, curLoc)
			}
		}
	}

	tabsize := int(buf.Settings["tabsize"].(float64))
	softwrap := buf.Settings["softwrap"].(bool)
	indentrunes := []rune(buf.Settings["indentchar"].(string))
	// if empty indentchar settings, use space
	if indentrunes == nil || len(indentrunes) == 0 {
		indentrunes = []rune{' '}
	}
	indentchar := indentrunes[0]

	start := buf.Cursor.Y
	if buf.Settings["syntax"].(bool) && buf.syntaxDef != nil {
		if start > 0 && buf.lines[start-1].rehighlight {
			buf.highlighter.ReHighlightLine(buf, start-1)
			buf.lines[start-1].rehighlight = false
		}

		buf.highlighter.ReHighlightStates(buf, start)

		buf.highlighter.HighlightMatches(buf, top, top+height)
	}

	c.lines = make([][]*Char, 0)

	viewLine := 0
	lineN := top

	curStyle := defStyle
	for viewLine < height {
		if lineN >= len(buf.lines) {
			break
		}

		lineStr := buf.Line(lineN)
		line := []rune(lineStr)

		colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize)
		if colN < 0 {
			colN = len(line)
		}
		viewCol := -startOffset
		if startStyle != nil {
			curStyle = *startStyle
		}

		// We'll either draw the length of the line, or the width of the screen
		// whichever is smaller
		lineLength := min(StringWidth(lineStr, tabsize), width)
		c.lines = append(c.lines, make([]*Char, lineLength))

		wrap := false
		// We only need to wrap if the length of the line is greater than the width of the terminal screen
		if softwrap && StringWidth(lineStr, tabsize) > width {
			wrap = true
			// We're going to draw the entire line now
			lineLength = StringWidth(lineStr, tabsize)
		}

		for viewCol < lineLength {
			if colN >= len(line) {
				break
			}
			if group, ok := buf.Match(lineN)[colN]; ok {
				curStyle = GetColor(group.String())
			}

			char := line[colN]

			if viewCol >= 0 {
				st := curStyle
				if colN == matchingBrace.X && lineN == matchingBrace.Y && !buf.Cursor.HasSelection() {
					st = curStyle.Reverse(true)
				}
				if viewCol < len(c.lines[viewLine]) {
					c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, st, 1}
				}
			}
			if char == '\t' {
				charWidth := tabsize - (viewCol+left)%tabsize
				if viewCol >= 0 {
					c.lines[viewLine][viewCol].drawChar = indentchar
					c.lines[viewLine][viewCol].width = charWidth

					indentStyle := curStyle
					ch := buf.Settings["indentchar"].(string)
					if group, ok := colorscheme["indent-char"]; ok && !IsStrWhitespace(ch) && ch != "" {
						indentStyle = group
					}

					c.lines[viewLine][viewCol].style = indentStyle
				}

				for i := 1; i < charWidth; i++ {
					viewCol++
					if viewCol >= 0 && viewCol < lineLength && viewCol < len(c.lines[viewLine]) {
						c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
					}
				}
				viewCol++
			} else if runewidth.RuneWidth(char) > 1 {
				charWidth := runewidth.RuneWidth(char)
				if viewCol >= 0 {
					c.lines[viewLine][viewCol].width = charWidth
				}
				for i := 1; i < charWidth; i++ {
					viewCol++
					if viewCol >= 0 && viewCol < lineLength && viewCol < len(c.lines[viewLine]) {
						c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
					}
				}
				viewCol++
			} else {
				viewCol++
			}
			colN++

			if wrap && viewCol >= width {
				viewLine++

				// If we go too far soft wrapping we have to cut off
				if viewLine >= height {
					break
				}

				nextLine := line[colN:]
				lineLength := min(StringWidth(string(nextLine), tabsize), width)
				c.lines = append(c.lines, make([]*Char, lineLength))

				viewCol = 0
			}

		}
		if group, ok := buf.Match(lineN)[len(line)]; ok {
			curStyle = GetColor(group.String())
		}

		// newline
		viewLine++
		lineN++
	}

	for i := top; i < top+height; i++ {
		if i >= buf.NumLines {
			break
		}
		buf.SetMatch(i, nil)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net"
	"os"

	"github.com/datawire/teleproxy/pkg/supervisor"
	"github.com/pkg/errors"
)

// Daemon represents the state of the Playpen Daemon
type Daemon struct {
	teleproxy string

	network        Resource
	cluster        *KCluster
	bridge         Resource
	trafficMgr     Resource
	intercepts     []*InterceptInfo
	interceptables []string
}

// RunAsDaemon is the main function when executing as the daemon
func RunAsDaemon() error {
	if os.Geteuid() != 0 {
		return errors.New("playpen daemon must run as root")
	}

	d := &Daemon{}

	sup := supervisor.WithContext(context.Background())
	sup.Logger = SetUpLogging()
	sup.Supervise(&supervisor.Worker{
		Name: "daemon",
		Work: d.acceptLoop,
	})
	sup.Supervise(&supervisor.Worker{
		Name:     "signal",
		Requires: []string{"daemon"},
		Work:     WaitForSignal,
	})
	sup.Supervise(&supervisor.Worker{
		Name:     "setup",
		Requires: []string{"daemon"},
		Work: func(p *supervisor.Process) error {
			if err := d.MakeNetOverride(p); err != nil {
				return err
			}
			p.Ready()
			return nil
		},
	})

	sup.Logger.Printf("---")
	sup.Logger.Printf("Playpen daemon %s starting...", displayVersion)
	sup.Logger.Printf("PID is %d", os.Getpid())
	runErrors := sup.Run()

	sup.Logger.Printf("")
	if len(runErrors) > 0 {
		sup.Logger.Printf("Daemon has exited with %d error(s):", len(runErrors))
		for _, err := range runErrors {
			sup.Logger.Printf("- %v", err)
		}
	}
	sup.Logger.Printf("Playpen daemon %s is done.", displayVersion)
	return errors.New("playpen daemon has exited")
}

func (d *Daemon) acceptLoop(p *supervisor.Process) error {
	// Listen on unix domain socket
	unixListener, err := net.Listen("unix", socketName)
	if err != nil {
		return errors.Wrap(err, "chmod")
	}
	err = os.Chmod(socketName, 0777)
	if err != nil {
		return errors.Wrap(err, "chmod")
	}

	p.Ready()
	Notify(p, "Running")
	defer Notify(p, "Terminated")

	return p.DoClean(
		func() error {
			for {
				conn, err := unixListener.Accept()
				if err != nil {
					return errors.Wrap(err, "accept")
				}
				_ = p.Go(func(p *supervisor.Process) error {
					return d.handle(p, conn)
				})
			}
		},
		unixListener.Close,
	)
}

func (d *Daemon) handle(p *supervisor.Process, conn net.Conn) error {
	defer conn.Close()

	decoder := json.NewDecoder(conn)
	data := &ClientMessage{}
	if err := decoder.Decode(data); err != nil {
		p.Logf("Failed to read message: %v", err)
		fmt.Fprintln(conn, "API mismatch. Server", displayVersion)
		return nil
	}
	if data.APIVersion != apiVersion {
		p.Logf("API version mismatch (got %d, need %d)", data.APIVersion, apiVersion)
		fmt.Fprintf(conn, "API version mismatch (got %d, server %s)", data.APIVersion, displayVersion)
		return nil
	}
	p.Logf("Received command: %q", data.Args)

	err := d.handleCommand(p, conn, data)
	if err != nil {
		p.Logf("Command processing failed: %v", err)
	}

	p.Log("Done")
	return nil
}
<commit_msg>Track Intercept resources, not info values<commit_after>package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net"
	"os"

	"github.com/datawire/teleproxy/pkg/supervisor"
	"github.com/pkg/errors"
)

// Daemon represents the state of the Playpen Daemon
type Daemon struct {
	teleproxy string

	network        Resource
	cluster        *KCluster
	bridge         Resource
	trafficMgr     *TrafficManager
	intercepts     []*Intercept
	interceptables []string
}

// RunAsDaemon is the main function when executing as the daemon
func RunAsDaemon() error {
	if os.Geteuid() != 0 {
		return errors.New("playpen daemon must run as root")
	}

	d := &Daemon{}

	sup := supervisor.WithContext(context.Background())
	sup.Logger = SetUpLogging()
	sup.Supervise(&supervisor.Worker{
		Name: "daemon",
		Work: d.acceptLoop,
	})
	sup.Supervise(&supervisor.Worker{
		Name:     "signal",
		Requires: []string{"daemon"},
		Work:     WaitForSignal,
	})
	sup.Supervise(&supervisor.Worker{
		Name:     "setup",
		Requires: []string{"daemon"},
		Work: func(p *supervisor.Process) error {
			if err := d.MakeNetOverride(p); err != nil {
				return err
			}
			p.Ready()
			return nil
		},
	})

	sup.Logger.Printf("---")
	sup.Logger.Printf("Playpen daemon %s starting...", displayVersion)
	sup.Logger.Printf("PID is %d", os.Getpid())
	runErrors := sup.Run()

	sup.Logger.Printf("")
	if len(runErrors) > 0 {
		sup.Logger.Printf("Daemon has exited with %d error(s):", len(runErrors))
		for _, err := range runErrors {
			sup.Logger.Printf("- %v", err)
		}
	}
	sup.Logger.Printf("Playpen daemon %s is done.", displayVersion)
	return errors.New("playpen daemon has exited")
}

func (d *Daemon) acceptLoop(p *supervisor.Process) error {
	// Listen on unix domain socket
	unixListener, err := net.Listen("unix", socketName)
	if err != nil {
		return errors.Wrap(err, "chmod")
	}
	err = os.Chmod(socketName, 0777)
	if err != nil {
		return errors.Wrap(err, "chmod")
	}

	p.Ready()
	Notify(p, "Running")
	defer Notify(p, "Terminated")

	return p.DoClean(
		func() error {
			for {
				conn, err := unixListener.Accept()
				if err != nil {
					return errors.Wrap(err, "accept")
				}
				_ = p.Go(func(p *supervisor.Process) error {
					return d.handle(p, conn)
				})
			}
		},
		unixListener.Close,
	)
}

func (d *Daemon) handle(p *supervisor.Process, conn net.Conn) error {
	defer conn.Close()

	decoder := json.NewDecoder(conn)
	data := &ClientMessage{}
	if err := decoder.Decode(data); err != nil {
		p.Logf("Failed to read message: %v", err)
		fmt.Fprintln(conn, "API mismatch. Server", displayVersion)
		return nil
	}
	if data.APIVersion != apiVersion {
		p.Logf("API version mismatch (got %d, need %d)", data.APIVersion, apiVersion)
		fmt.Fprintf(conn, "API version mismatch (got %d, server %s)", data.APIVersion, displayVersion)
		return nil
	}
	p.Logf("Received command: %q", data.Args)

	err := d.handleCommand(p, conn, data)
	if err != nil {
		p.Logf("Command processing failed: %v", err)
	}

	p.Log("Done")
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"

	"github.com/spf13/cobra"

	"github.com/rigelrozanski/common"
)

// RootCmd is the root cobra command of this program
var RootCmd = &cobra.Command{
	Use:   "shelldown [markdown-file-paths]",
	Short: "Generate shell scripts for specially formatted markdown files",
	RunE:  rootCmd,
}

func main() {
	err := RootCmd.Execute()
	if err != nil {
		fmt.Printf("%+v\n", err)
	}
}

func rootCmd(cmd *cobra.Command, args []string) error {

	if len(args) == 0 {
		return errors.New("must include files to script")
	}

	// Loop through all the files provided
	for _, filepath := range args {

		// Make sure the file exists
		//fmt.Printf("debug opening file %v\n", filepath)
		if _, err := os.Stat(filepath); os.IsNotExist(err) { //file doesn't exist
			return fmt.Errorf("Could not load file %v", filepath)
		}

		// Read file into a string object
		raw, err := common.readLines(filepath)
		if err != nil {
			return err
		}

		// Get the core code block
		shellCode := getShellCodeBlock(raw)

		// If the codeblock is empty just move on to the next .md file
		if shellCode == nil {
			fmt.Printf("file %v doesn't contain a valid shelldown header, Skipping...\n", filepath)
			continue
		}

		//replace all the holders in the codeblock
		shellCode, err = setCodeBlockHolders(shellCode, raw)
		if err != nil {
			return err
		}

		//set autogen text
		shellCode = writeAutoGenText(shellCode)

		//write the codeblock lines
		shellPath := filepath + ".sh"
		common.writeLines(shellCode, shellPath)
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////

const (

	//Start of the shell code stored within the markdown file
	scriptStart = "<!---"

	//End of the shell code stored within the markdown file
	scriptEnd = "-->"

	//Marker representing to grab a markdown codeblock for the shell script
	markerGet = "shelldown"

	//Marker representing to set a markdown codeblock for the shell script
	markerSet = "#shelldown"

	//Text to include on the top of the shell autogenerated shell script
	autoGenText = "#This script was generated with shelldown, see github.com/rigelrozanski/shelldown"
)

var (
	//regex scripts for determining placeholders in the shell script template
	regexIndex = regexp.MustCompile("([-?\\d]+)")
	regexSet   = regexp.MustCompile("(" + markerSet + "\\[\\d+\\]\\[-?\\d+\\])")
)

//Get the core code block for the shell script
func getShellCodeBlock(raw []string) []string {
	if !strings.HasPrefix(raw[0], scriptStart) {
		//fmt.Printf("debug %v %v\n", raw[0], scriptStart)
		return nil
	}

	//determine end line
	endCB := 0
	for i, line := range raw {
		if strings.HasPrefix(line, scriptEnd) && i > 0 {
			endCB = i //set to the previous line
			break
		}
	}

	//if no valid end codeblock was found
	if endCB == 0 {
		return nil
	}

	return raw[1:endCB]
}

func setCodeBlockHolders(shellCode, raw []string) ([]string, error) {
	var out []string
	for _, line := range shellCode {
		appendLine := line
		if strings.Contains(line, markerGet) {

			//get the index and the full holder (ex. shelldown[7][0])
			reg1 := regexSet.FindAllString(line, 1)
			if len(reg1) != 1 {
				return nil, errors.New("bad regexSet length")
			}

			holderStr := reg1[0]
			reg2 := regexIndex.FindAllString(holderStr, 2)
			if len(reg2) != 2 { //there should be 2 index files (ex. #shelldown[7][9])
				return nil, errors.New("bad regexIndex length")
			}

			index1, err := strconv.Atoi(reg2[0])
			if err != nil {
				return nil, err
			}

			index2, err := strconv.Atoi(reg2[1])
			if err != nil {
				return nil, err
			}

			holderValArr, err := getMarkdownHolder(raw, index1)
			if err != nil {
				return nil, err
			}

			//fmt.Printf("debug holder %v, index1 %v, index2 %v\n", holderValArr, index1, index2)
			if index2 == -1 { //special case to print all of the lines
				var appendLineArr []string
				for _, val := range holderValArr {

					//skip if a blank line
					if len(val) == 0 {
						continue
					}

					innerAppendLine := strings.Replace(line, holderStr, val, -1)
					appendLineArr = append(appendLineArr, innerAppendLine)
				}
				appendLine = strings.Join(appendLineArr, "\n")

			} else {
				if len(holderValArr) <= index2 {
					return nil, fmt.Errorf("index of %v  out of range for placeholder %v, holderValArr %v",
						index2, holderStr, holderValArr)
				}
				appendLine = strings.Replace(line, holderStr, holderValArr[index2], -1)

			}
		}
		out = append(out, appendLine)
	}
	return out, nil
}

//Get the core code block for the shell script
func getMarkdownHolder(raw []string, index int) ([]string, error) {

	startCB, endCB := -1, -1
	markerStr := fmt.Sprintf("%v[%v]", markerGet, index)

	for i, line := range raw {
		if startCB == -1 &&
			strings.Contains(line, markerStr) &&
			strings.HasPrefix(line, "```") {
			startCB = i + 1
			break
		}
	}

	for i := startCB + 1; i < len(raw); i++ {
		if strings.HasPrefix(raw[i], "```") {
			endCB = i
			break
		}
	}

	if startCB == -1 || endCB == -1 {
		return nil, fmt.Errorf("invalid codeblock for index %v", index)
	}

	//fmt.Printf("debug start %v, end %v, index %v\n", startCB, endCB, index)
	return raw[startCB:endCB], nil
}

func writeAutoGenText(shellcode []string) []string {
	return append(
		[]string{shellcode[0], autoGenText},
		shellcode[1:]...,
	)
}
<commit_msg>expose common funcs<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"

	"github.com/spf13/cobra"

	"github.com/rigelrozanski/common"
)

// RootCmd is the root cobra command of this program
var RootCmd = &cobra.Command{
	Use:   "shelldown [markdown-file-paths]",
	Short: "Generate shell scripts for specially formatted markdown files",
	RunE:  rootCmd,
}

func main() {
	err := RootCmd.Execute()
	if err != nil {
		fmt.Printf("%+v\n", err)
	}
}

func rootCmd(cmd *cobra.Command, args []string) error {

	if len(args) == 0 {
		return errors.New("must include files to script")
	}

	// Loop through all the files provided
	for _, filepath := range args {

		// Make sure the file exists
		//fmt.Printf("debug opening file %v\n", filepath)
		if _, err := os.Stat(filepath); os.IsNotExist(err) { //file doesn't exist
			return fmt.Errorf("Could not load file %v", filepath)
		}

		// Read file into a string object
		raw, err := common.ReadLines(filepath)
		if err != nil {
			return err
		}

		// Get the core code block
		shellCode := getShellCodeBlock(raw)

		// If the codeblock is empty just move on to the next .md file
		if shellCode == nil {
			fmt.Printf("file %v doesn't contain a valid shelldown header, Skipping...\n", filepath)
			continue
		}

		//replace all the holders in the codeblock
		shellCode, err = setCodeBlockHolders(shellCode, raw)
		if err != nil {
			return err
		}

		//set autogen text
		shellCode = writeAutoGenText(shellCode)

		//write the codeblock lines
		shellPath := filepath + ".sh"
		common.WriteLines(shellCode, shellPath)
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////

const (

	//Start of the shell code stored within the markdown file
	scriptStart = "<!---"

	//End of the shell code stored within the markdown file
	scriptEnd = "-->"

	//Marker representing to grab a markdown codeblock for the shell script
	markerGet = "shelldown"

	//Marker representing to set a markdown codeblock for the shell script
	markerSet = "#shelldown"

	//Text to include on the top of the shell autogenerated shell script
	autoGenText = "#This script was generated with shelldown, see github.com/rigelrozanski/shelldown"
)

var (
	//regex scripts for determining placeholders in the shell script template
	regexIndex = regexp.MustCompile("([-?\\d]+)")
	regexSet   = regexp.MustCompile("(" + markerSet + "\\[\\d+\\]\\[-?\\d+\\])")
)

//Get the core code block for the shell script
func getShellCodeBlock(raw []string) []string {
	if !strings.HasPrefix(raw[0], scriptStart) {
		//fmt.Printf("debug %v %v\n", raw[0], scriptStart)
		return nil
	}

	//determine end line
	endCB := 0
	for i, line := range raw {
		if strings.HasPrefix(line, scriptEnd) && i > 0 {
			endCB = i //set to the previous line
			break
		}
	}

	//if no valid end codeblock was found
	if endCB == 0 {
		return nil
	}

	return raw[1:endCB]
}

func setCodeBlockHolders(shellCode, raw []string) ([]string, error) {
	var out []string
	for _, line := range shellCode {
		appendLine := line
		if strings.Contains(line, markerGet) {

			//get the index and the full holder (ex. shelldown[7][0])
			reg1 := regexSet.FindAllString(line, 1)
			if len(reg1) != 1 {
				return nil, errors.New("bad regexSet length")
			}

			holderStr := reg1[0]
			reg2 := regexIndex.FindAllString(holderStr, 2)
			if len(reg2) != 2 { //there should be 2 index files (ex. #shelldown[7][9])
				return nil, errors.New("bad regexIndex length")
			}

			index1, err := strconv.Atoi(reg2[0])
			if err != nil {
				return nil, err
			}

			index2, err := strconv.Atoi(reg2[1])
			if err != nil {
				return nil, err
			}

			holderValArr, err := getMarkdownHolder(raw, index1)
			if err != nil {
				return nil, err
			}

			//fmt.Printf("debug holder %v, index1 %v, index2 %v\n", holderValArr, index1, index2)
			if index2 == -1 { //special case to print all of the lines
				var appendLineArr []string
				for _, val := range holderValArr {

					//skip if a blank line
					if len(val) == 0 {
						continue
					}

					innerAppendLine := strings.Replace(line, holderStr, val, -1)
					appendLineArr = append(appendLineArr, innerAppendLine)
				}
				appendLine = strings.Join(appendLineArr, "\n")

			} else {
				if len(holderValArr) <= index2 {
					return nil, fmt.Errorf("index of %v  out of range for placeholder %v, holderValArr %v",
						index2, holderStr, holderValArr)
				}
				appendLine = strings.Replace(line, holderStr, holderValArr[index2], -1)

			}
		}
		out = append(out, appendLine)
	}
	return out, nil
}

//Get the core code block for the shell script
func getMarkdownHolder(raw []string, index int) ([]string, error) {

	startCB, endCB := -1, -1
	markerStr := fmt.Sprintf("%v[%v]", markerGet, index)

	for i, line := range raw {
		if startCB == -1 &&
			strings.Contains(line, markerStr) &&
			strings.HasPrefix(line, "```") {
			startCB = i + 1
			break
		}
	}

	for i := startCB + 1; i < len(raw); i++ {
		if strings.HasPrefix(raw[i], "```") {
			endCB = i
			break
		}
	}

	if startCB == -1 || endCB == -1 {
		return nil, fmt.Errorf("invalid codeblock for index %v", index)
	}

	//fmt.Printf("debug start %v, end %v, index %v\n", startCB, endCB, index)
	return raw[startCB:endCB], nil
}

func writeAutoGenText(shellcode []string) []string {
	return append(
		[]string{shellcode[0], autoGenText},
		shellcode[1:]...,
	)
}
<|endoftext|>


<commit_before>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/alm"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	d "github.com/mobingilabs/mobingi-sdk-go/pkg/debug"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/pretty"
	"github.com/spf13/cobra"
)

func StackDescribeCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "describe",
		Short: "display stack details",
		Long: `Display stack details. If you specify the '--out=[filename]' option,
make sure you provide the full path of the file. If the path has
space(s) in it, make sure to surround it with double quotes.

Valid format values: min (default), json, raw

Examples:

  $ ` + cmdline.Args0() + ` stack describe --id=58c2297d25645-Y6NSE4VjP-tk
  $ ` + cmdline.Args0() + ` stack describe --id=58c2297d25645-Y6NSE4VjP-tk --fmt=json`,
		Run: describe,
	}

	cmd.Flags().String("id", "", "stack id")
	return cmd
}

func describe(cmd *cobra.Command, args []string) {
	sess, err := clisession()
	cli.ErrorExit(err, 1)

	svc := alm.New(sess)
	in := &alm.StackDescribeInput{
		StackId: cli.GetCliStringFlag(cmd, "id"),
	}

	resp, body, err := svc.Describe(in)
	cli.ErrorExit(err, 1)
	exitOn401(resp)

	// we process `--fmt=raw` option first
	out := cli.GetCliStringFlag(cmd, "out")
	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))
		if out != "" {
			err = ioutil.WriteFile(out, body, 0644)
			cli.ErrorExit(err, 1)
		}
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		js := pretty.JSON(string(body), indent)
		fmt.Println(js)

		// write to file option
		if out != "" {
			err = ioutil.WriteFile(out, []byte(js), 0644)
			cli.ErrorExit(err, 1)
		}
	default:
		if pfmt == "min" || pfmt == "" {
			var stacks []alm.DescribeStack
			var stack alm.DescribeStack

			switch sess.Config.ApiVersion {
			case 3:
				err = json.Unmarshal(body, &stack)
				cli.ErrorExit(err, 1)
			default:
				err = json.Unmarshal(body, &stacks)
				cli.ErrorExit(err, 1)
				stack = stacks[0]
			}

			w := tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
			fmt.Fprintf(w, "INSTANCE ID\tINSTANCE TYPE\tINSTANCE MODEL\tPUBLIC DNS\tPUBLIC IP\tPRIVATE IP\tSTATUS\n")
			for _, inst := range stack.Instances {
				instype := "on-demand"
				if inst.InstanceLifecycle == "spot" {
					instype = inst.InstanceLifecycle
				}

				pubip := string(inst.PublicIpAddress)
				pubip = strings.TrimLeft(pubip, "\"")
				pubip = strings.TrimRight(pubip, "\"")

				// try if ip is json (alicloud)
				type pubip_t struct {
					IpAddress []string
				}

				var ips pubip_t
				err = json.Unmarshal(inst.PublicIpAddress, &ips)
				if err == nil {
					pubip = strings.Join(ips.IpAddress, ",")
				}

				state := inst.State.Name
				if state == "" {
					state = fmt.Sprintf("%s", inst.Status)
				}

				fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
					inst.InstanceId,
					instype,
					inst.InstanceType,
					inst.PublicDnsName,
					pubip,
					inst.PrivateIpAddress,
					strings.ToLower(state))
			}

			d.Info("[instances]")
			w.Flush()

			// separate table for configurations, if any
			if stack.Configuration.Configurations != nil {
				w = tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
				fmt.Fprintf(w, "ROLE\tFLAG\tCONTAINER\n")
				var cnfs []alm.Configurations
				err = json.Unmarshal(stack.Configuration.Configurations, &cnfs)
				cli.ErrorExit(err, 1)

				for _, inst := range cnfs {
					var image string
					if inst.Container != nil {
						contmap := inst.Container.(map[string]interface{})
						for k, v := range contmap {
							if k == "image" {
								image = fmt.Sprintf("%s", v)
							}
						}
					}

					fmt.Fprintf(w, "%s\t%s\t%s\n", inst.Role, inst.Flag, image)
				}

				fmt.Println()
				d.Info("[configurations]")
				w.Flush()
			}
		}
	}
}
<commit_msg>Add flag in describe table.<commit_after>package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/mobingi/mobingi-cli/pkg/cli"
	"github.com/mobingilabs/mobingi-sdk-go/mobingi/alm"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/cmdline"
	d "github.com/mobingilabs/mobingi-sdk-go/pkg/debug"
	"github.com/mobingilabs/mobingi-sdk-go/pkg/pretty"
	"github.com/spf13/cobra"
)

func StackDescribeCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "describe",
		Short: "display stack details",
		Long: `Display stack details. If you specify the '--out=[filename]' option,
make sure you provide the full path of the file. If the path has
space(s) in it, make sure to surround it with double quotes.

Valid format values: min (default), json, raw

Examples:

  $ ` + cmdline.Args0() + ` stack describe --id=58c2297d25645-Y6NSE4VjP-tk
  $ ` + cmdline.Args0() + ` stack describe --id=58c2297d25645-Y6NSE4VjP-tk --fmt=json`,
		Run: describe,
	}

	cmd.Flags().String("id", "", "stack id")
	return cmd
}

func describe(cmd *cobra.Command, args []string) {
	sess, err := clisession()
	cli.ErrorExit(err, 1)

	svc := alm.New(sess)
	in := &alm.StackDescribeInput{
		StackId: cli.GetCliStringFlag(cmd, "id"),
	}

	resp, body, err := svc.Describe(in)
	cli.ErrorExit(err, 1)
	exitOn401(resp)

	// we process `--fmt=raw` option first
	out := cli.GetCliStringFlag(cmd, "out")
	pfmt := cli.GetCliStringFlag(cmd, "fmt")
	switch pfmt {
	case "raw":
		fmt.Println(string(body))
		if out != "" {
			err = ioutil.WriteFile(out, body, 0644)
			cli.ErrorExit(err, 1)
		}
	case "json":
		indent := cli.GetCliIntFlag(cmd, "indent")
		js := pretty.JSON(string(body), indent)
		fmt.Println(js)

		// write to file option
		if out != "" {
			err = ioutil.WriteFile(out, []byte(js), 0644)
			cli.ErrorExit(err, 1)
		}
	default:
		if pfmt == "min" || pfmt == "" {
			var stacks []alm.DescribeStack
			var stack alm.DescribeStack

			switch sess.Config.ApiVersion {
			case 3:
				err = json.Unmarshal(body, &stack)
				cli.ErrorExit(err, 1)
			default:
				err = json.Unmarshal(body, &stacks)
				cli.ErrorExit(err, 1)
				stack = stacks[0]
			}

			w := tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
			fmt.Fprintf(w, "INSTANCE ID\tINSTANCE TYPE\tINSTANCE MODEL\tPUBLIC DNS\tPUBLIC IP\tPRIVATE IP\tFLAG\tSTATUS\n")
			for _, inst := range stack.Instances {
				instype := "on-demand"
				if inst.InstanceLifecycle == "spot" {
					instype = inst.InstanceLifecycle
				}

				pubip := string(inst.PublicIpAddress)
				pubip = strings.TrimLeft(pubip, "\"")
				pubip = strings.TrimRight(pubip, "\"")

				// try if ip is json (alicloud)
				type pubip_t struct {
					IpAddress []string
				}

				var ips pubip_t
				err = json.Unmarshal(inst.PublicIpAddress, &ips)
				if err == nil {
					pubip = strings.Join(ips.IpAddress, ",")
				}

				// try to extract flag from key name
				flag := inst.KeyName
				if flag == "" {
					flag = inst.KeyPairName
				}

				if flag != "" {
					parts := strings.Split(flag, "-")
					if len(parts) > 1 {
						flag = parts[len(parts)-1]
					} else {
						flag = ""
					}
				}

				state := inst.State.Name
				if state == "" {
					state = fmt.Sprintf("%s", inst.Status)
				}

				fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
					inst.InstanceId,
					instype,
					inst.InstanceType,
					inst.PublicDnsName,
					pubip,
					inst.PrivateIpAddress,
					flag,
					strings.ToLower(state))
			}

			d.Info("[instances]")
			w.Flush()

			// separate table for configurations, if any
			if stack.Configuration.Configurations != nil {
				w = tabwriter.NewWriter(os.Stdout, 0, 10, 5, ' ', 0)
				fmt.Fprintf(w, "ROLE\tFLAG\tCONTAINER\n")
				var cnfs []alm.Configurations
				err = json.Unmarshal(stack.Configuration.Configurations, &cnfs)
				cli.ErrorExit(err, 1)

				for _, inst := range cnfs {
					var image string
					if inst.Container != nil {
						contmap := inst.Container.(map[string]interface{})
						for k, v := range contmap {
							if k == "image" {
								image = fmt.Sprintf("%s", v)
							}
						}
					}

					fmt.Fprintf(w, "%s\t%s\t%s\n", inst.Role, inst.Flag, image)
				}

				fmt.Println()
				d.Info("[configurations]")
				w.Flush()
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
tchremote is a tool which uses the Tchaik REST API to act as a remote control. See --help for more details.
*/
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"strings"
)

const (
	HostEnv      = "TCH_ADDR"
	PlayerKeyEnv = "TCH_PLAYER_KEY"
)

var host string
var key string
var keys bool
var action string
var value string

func init() {
	flag.StringVar(&host, "addr", "", fmt.Sprintf("schema://host(:port) address of the REST API (or set %v)", HostEnv))
	flag.StringVar(&key, "key", "", fmt.Sprintf("the key which identifies the player to send actions to (or set %v)", PlayerKeyEnv))
	flag.BoolVar(&keys, "keys", false, "list all the keys on the host")
	flag.StringVar(&action, "action", "", "action to send to the player (requires -key, some require -value)")
	flag.StringVar(&value, "value", "", "value to send to the player")
}

func main() {
	flag.Parse()

	if host == "" {
		host = os.Getenv(HostEnv)
	}
	if host == "" {
		fmt.Printf("must use -addr or set %v\n", HostEnv)
		os.Exit(1)
	}

	if keys {
		list, err := getPlayerKeys()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		for _, k := range list {
			fmt.Println(k)
		}
		return
	}

	if key == "" {
		key = os.Getenv(PlayerKeyEnv)
	}
	if key == "" {
		fmt.Printf("must use -key or set %v\n", PlayerKeyEnv)
		os.Exit(1)
	}

	err := handleAction(action, value)
	if err != nil {
		fmt.Printf("error handling action: %v", err)
		os.Exit(1)
	}
}

func handleAction(action, value string) error {
	if value != "" {
		switch action {
		case "setTime", "setVolume":
			f, err := strconv.ParseFloat(value, 64)
			if err != nil {
				return err
			}
			return sendPlayerAction(f)

		case "setVolumeMute":
			b, err := strconv.ParseBool(value)
			if err != nil {
				return err
			}
			return sendPlayerAction(b)
		}
	}
	return sendPlayerAction(nil)
}

func getPlayerKeys() ([]string, error) {
	resp, err := http.Get(fmt.Sprintf("%v/api/players/", host))
	if err != nil {
		return nil, fmt.Errorf("error performing request: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response body: %v", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("error: %v", string(body))
	}

	data := struct {
		Keys []string `json:"keys"`
	}{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		return nil, fmt.Errorf("error unmarshalling response: %v", err)
	}
	return data.Keys, nil
}

func sendPlayerAction(value interface{}) error {
	data := struct {
		Action string      `json:"action"`
		Value  interface{} `json:"value,omitempty"`
	}{
		Action: action,
		Value:  value,
	}

	b, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("error marshalling JSON request body: %v", err)
	}
	requestURL := fmt.Sprintf("%v/api/players/%v", host, key)
	req, err := http.NewRequest("PUT", requestURL, bytes.NewReader(b))
	if err != nil {
		return fmt.Errorf("error creating request: %v", err)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("error performing request: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("error reading response body: %v", err)
		}
		return fmt.Errorf("error: %v", strings.TrimSpace(string(body)))
	}
	return nil
}
<commit_msg>Add support for creating new players to tchremote.<commit_after>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
tchremote is a tool which uses the Tchaik REST API to act as a remote control. See --help for more details.
*/
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"strings"
)

const (
	HostEnv      = "TCH_ADDR"
	PlayerKeyEnv = "TCH_PLAYER_KEY"
)

var host string
var key string
var keys bool
var action string
var value string
var create string

func init() {
	flag.StringVar(&host, "addr", "", fmt.Sprintf("schema://host(:port) address of the REST API (or set %v)", HostEnv))
	flag.StringVar(&key, "key", "", fmt.Sprintf("the key which identifies the player to send actions to (or set %v)", PlayerKeyEnv))
	flag.BoolVar(&keys, "keys", false, "list all the keys on the host")
	flag.StringVar(&action, "action", "", "action to send to the player (requires -key, some require -value)")
	flag.StringVar(&value, "value", "", "value to send to the player")
	flag.StringVar(&create, "create", "", "create a multi-player for the given -key")
}

func main() {
	flag.Parse()

	if host == "" {
		host = os.Getenv(HostEnv)
	}
	if host == "" {
		fmt.Printf("must use -addr or set %v\n", HostEnv)
		os.Exit(1)
	}

	if keys {
		list, err := getPlayerKeys()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		for _, k := range list {
			fmt.Println(k)
		}
		return
	}

	if key == "" {
		key = os.Getenv(PlayerKeyEnv)
	}
	if key == "" {
		fmt.Printf("must use -key or set %v\n", PlayerKeyEnv)
		os.Exit(1)
	}

	if create != "" {
		err := handleCreate(key, create)
		if err != nil {
			fmt.Printf("error creating player key: %v\n", err)
			os.Exit(1)
		}
		return
	}

	if action != "" {
		err := handleAction(action, value)
		if err != nil {
			fmt.Printf("error handling action: %v\n", err)
			os.Exit(1)
		}
	}

	player, err := getPlayer(key)
	if err != nil {
		fmt.Printf("error fetching key: %v\n", err)
		os.Exit(1)
	}
	b, err := json.MarshalIndent(player, "", "  ")
	if err != nil {
		fmt.Printf("error marshalling player: %v\n", err)
		os.Exit(1)
	}
	fmt.Println(string(b))
}

func handleCreate(key, create string) error {
	keys := strings.Split(create, ",")
	data := struct {
		Key        string   `json:"key"`
		PlayerKeys []string `json:"playerKeys"`
	}{
		Key:        key,
		PlayerKeys: keys,
	}
	b, err := json.Marshal(data)
	if err != nil {
		return err
	}
	resp, err := http.Post(fmt.Sprintf("%v/api/players/", host), "application/json", bytes.NewBuffer(b))
	if err != nil {
		return fmt.Errorf("error performing request: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusCreated {
		return fmt.Errorf("error creating player key: %v", err)
	}
	return nil
}

func handleAction(action, value string) error {
	if value != "" {
		switch action {
		case "setTime", "setVolume":
			f, err := strconv.ParseFloat(value, 64)
			if err != nil {
				return err
			}
			return sendPlayerAction(f)

		case "setVolumeMute":
			b, err := strconv.ParseBool(value)
			if err != nil {
				return err
			}
			return sendPlayerAction(b)
		}
	}
	return sendPlayerAction(nil)
}

func getPlayerKeys() ([]string, error) {
	resp, err := http.Get(fmt.Sprintf("%v/api/players/", host))
	if err != nil {
		return nil, fmt.Errorf("error performing request: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response body: %v", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("error: %v", string(body))
	}

	data := struct {
		Keys []string `json:"keys"`
	}{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		return nil, fmt.Errorf("error unmarshalling response: %v", err)
	}
	return data.Keys, nil
}

type Player struct {
	Key        string   `json:"key"`
	PlayerKeys []string `json:"playerKeys"`
}

func getPlayer(key string) (*Player, error) {
	resp, err := http.Get(fmt.Sprintf("%v/api/players/%v", host, key))
	if err != nil {
		return nil, fmt.Errorf("error performing request: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response body: %v", err)
	}

	var data Player
	err = json.Unmarshal(body, &data)
	if err != nil {
		return nil, fmt.Errorf("error unmarshalling response: %v", err)
	}
	return &data, nil
}

func sendPlayerAction(value interface{}) error {
	data := struct {
		Action string      `json:"action"`
		Value  interface{} `json:"value,omitempty"`
	}{
		Action: action,
		Value:  value,
	}

	b, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("error marshalling JSON request body: %v", err)
	}
	requestURL := fmt.Sprintf("%v/api/players/%v", host, key)
	req, err := http.NewRequest("PUT", requestURL, bytes.NewReader(b))
	if err != nil {
		return fmt.Errorf("error creating request: %v", err)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("error performing request: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("error reading response body: %v", err)
		}
		return fmt.Errorf("error: %v", strings.TrimSpace(string(body)))
	}
	return nil
}
<|endoftext|>


<commit_before>package main

/*
	"do this with that"
*/

import (
	"flag"
	"fmt"
	"github.com/whosonfirst/go-whosonfirst-crawl"
	// "github.com/whosonfirst/go-whosonfirst-geojson"
	"os"
	"os/exec"
	"runtime"
	"time"
)

func main() {

	dothis := flag.String("do-this", "", "...")
	fromthere := flag.String("from-there", "", "...")
	procs := flag.Int("procs", 200, "...")
	verbose := flag.Bool("verbose", false, "...")

	flag.Parse()

	runtime.GOMAXPROCS(*procs)

	cb := func(abs_path string, info os.FileInfo) error {

		t1 := time.Now()

		cmd := exec.Command(*dothis, abs_path)
		out, err := cmd.Output()

		t2 := time.Since(t1)

		if *verbose {
			fmt.Printf("failed to do this with %s: %v\n", abs_path, t2)
		}

		if err != nil {
			fmt.Printf("failed to do this with %s, because %v (%s)\n", abs_path, err, out)
			return err
		}

		if *verbose {
			fmt.Printf("%s", out)
		}

		return nil
	}

	c := crawl.NewCrawler(*fromthere)
	_ = c.Crawl(cb)

}
<commit_msg>fix copy for timer<commit_after>package main

/*
	"do this with that"
*/

import (
	"flag"
	"fmt"
	"github.com/whosonfirst/go-whosonfirst-crawl"
	// "github.com/whosonfirst/go-whosonfirst-geojson"
	"os"
	"os/exec"
	"runtime"
	"time"
)

func main() {

	dothis := flag.String("do-this", "", "...")
	fromthere := flag.String("from-there", "", "...")
	procs := flag.Int("procs", 200, "...")
	verbose := flag.Bool("verbose", false, "...")

	flag.Parse()

	runtime.GOMAXPROCS(*procs)

	cb := func(abs_path string, info os.FileInfo) error {

		t1 := time.Now()

		cmd := exec.Command(*dothis, abs_path)
		out, err := cmd.Output()

		t2 := time.Since(t1)

		if *verbose {
			fmt.Printf("time to do this with %s: %v\n", abs_path, t2)
		}

		if err != nil {
			fmt.Printf("failed to do this with %s, because %v (%s)\n", abs_path, err, out)
			return err
		}

		if *verbose {
			fmt.Printf("%s", out)
		}

		return nil
	}

	c := crawl.NewCrawler(*fromthere)
	_ = c.Crawl(cb)

}
<|endoftext|>


<commit_before>package nasa

import (
	"strings"
	"testing"
	"time"
)

func TestNeoFeed(t *testing.T) {
	type neotests struct {
		startText, endText string
		nl                 *NeoList
		err                error
	}
	var tests = []neotests{
		{
			startText: "2017-05-11",
			endText:   "2017-05-12",
			nl:        &NeoList{ElementCount: 18},
		},
		{
			startText: "1000-05-11",
			endText:   "1000-05-12",
			nl:        &NeoList{ElementCount: 0},
		},
	}

	for _, v := range tests {
		start, err := time.Parse("2006-01-02", v.startText)
		if err != nil {
			t.Fatal(err)
		}
		end, err := time.Parse("2006-01-02", v.endText)
		if err != nil {
			t.Fatal(err)
		}
		nl, err := NeoFeed(start, end)
		if err != v.err {
			t.Errorf("NeoFeed returned wrong error got %v, want %v", err, v.err)
		}
		if nl == nil {
			if v.nl != nil {
				t.Errorf("NeoFeed returned NeoList when %v was expected", nil)
			}
			continue
		}
		if nl.ElementCount != v.nl.ElementCount {
			t.Errorf("NeoFeed returned wrong element count got %d, want %d", nl.ElementCount, v.nl.ElementCount)
		}
		if !strings.Contains(nl.String(), "Near Earth Objects From:") {
			t.Errorf("NeoFeed return an invalid neolist, not valid NeoList stringer")
		}
	}
}
<commit_msg>Fix neofeed tests, in case neo values change<commit_after>package nasa

import (
	"strings"
	"testing"
	"time"
)

func TestNeoFeed(t *testing.T) {
	type neotests struct {
		startText, endText string
		nl                 *NeoList
		err                error
	}
	var tests = []neotests{
		{
			startText: "2017-05-11",
			endText:   "2017-05-12",
			nl:        &NeoList{ElementCount: 1},
		},
		{
			startText: "1000-05-11",
			endText:   "1000-05-12",
			nl:        &NeoList{ElementCount: 0},
		},
	}

	for _, v := range tests {
		start, err := time.Parse("2006-01-02", v.startText)
		if err != nil {
			t.Fatal(err)
		}
		end, err := time.Parse("2006-01-02", v.endText)
		if err != nil {
			t.Fatal(err)
		}
		nl, err := NeoFeed(start, end)
		if err != v.err {
			t.Errorf("NeoFeed returned wrong error got %v, want %v", err, v.err)
		}
		if nl == nil {
			if v.nl != nil {
				t.Errorf("NeoFeed returned NeoList when %v was expected", nil)
			}
			continue
		}
		if v.nl.ElementCount == 0 && nl.ElementCount != v.nl.ElementCount {
			t.Errorf("NeoFeed returned wrong element count got %d, want %d", nl.ElementCount, v.nl.ElementCount)
		}
		if v.nl.ElementCount > 0 && nl.ElementCount < v.nl.ElementCount {
			t.Errorf("NeoFeed returned wrong element count got %d, want >1", nl.ElementCount)
		}

		if !strings.Contains(nl.String(), "Near Earth Objects From:") {
			t.Errorf("NeoFeed return an invalid neolist, not valid NeoList stringer")
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/THECALLR/sdk-go"
)

func main() {

	// initialize instance Callr
	callr.Setup("login", "password", nil)

	// an optional third parameter let you add options like proxy support
	// proxy must be in url standard format
	// http[s]://user:password@host:port
	// http[s]://host:port
	// http[s]://host

	// var config callr.Config
	// config.Proxy = "http://foo:bar@example.com:8080"
	// callr.Setup("login", "password", &config)

	// Example to send a SMS
	// 1. "call" method: each parameter of the method as an argument
	result, err := callr.Call("sms.send", "CALLR", "+33123456789", "Hello, world", map[string]interface{}{
		"flash_message": false,
	})

	// error management
	if err != nil {
		fmt.Println("Code:", err.Code)
		fmt.Println("Message:", err.Msg)
		fmt.Println("Data:", err.Data)
	} else {
		fmt.Println(result)
	}

	// 2. "send" method: parameter of the method is an array
	my_array := []interface{}{
		"CALLR",
		"+33123456789",
		"Hello, world",
		map[string]interface{}{
			"flash_message": false,
		},
	}
	result, err = callr.Send("sms.send", my_array)

	// error management
	if err != nil {
		fmt.Println("Code:", err.Code)
		fmt.Println("Message:", err.Msg)
		fmt.Println("Data:", err.Data)
	} else {
		fmt.Println(result)
	}
}
<commit_msg>update(sample): add retrieval of credentials from environment variables, destination number passed as parameter<commit_after>package main

import (
	"fmt"
	"os"
	"github.com/THECALLR/sdk-go"
)

func main() {

	// initialize instance Callr
	// retrieve CALLR credentials from environment variables
	callr.Setup(os.Getenv("CALLR_LOGIN"), os.Getenv("CALLR_PASS"), nil)

	// an optional third parameter let you add options like proxy support
	// proxy must be in url standard format
	// http[s]://user:password@host:port
	// http[s]://host:port
	// http[s]://host

	// var config callr.Config
	// config.Proxy = "http://foo:bar@example.com:8080"
	// callr.Setup("login", "password", &config)

	// check for destination phone number parameter
	if len(os.Args) < 2 {
		fmt.Println("Please supply destination phone number!")
		os.Exit(1)
	}

	// Example to send a SMS
	// 1. "call" method: each parameter of the method as an argument
	result, err := callr.Call("sms.send", "SMS", os.Args[1], "Hello, world", map[string]interface{}{
		"flash_message": false,
	})

	// error management
	if err != nil {
		fmt.Println("Code:", err.Code)
		fmt.Println("Message:", err.Msg)
		fmt.Println("Data:", err.Data)
		os.Exit(1)
	} else {
		fmt.Println(result)
	}

	// 2. "send" method: parameter of the method is an array
	my_array := []interface{}{
		"SMS",
		 os.Args[1],
		"Hello, world",
		map[string]interface{}{
			"flash_message": false,
		},
	}
	result, err = callr.Send("sms.send", my_array)

	// error management
	if err != nil {
		fmt.Println("Code:", err.Code)
		fmt.Println("Message:", err.Msg)
		fmt.Println("Data:", err.Data)
		os.Exit(1)
	} else {
		fmt.Println(result)
	}
}
<|endoftext|>