<commit_before>package main

import (
  "flag"
  "fmt"
  "io"
  "os"
  "path/filepath"
  "crypto/elliptic"
  "crypto/ecdsa"
  "crypto/x509"
//  "crypto/x509/pkix"
  "crypto/rand"
  "encoding/pem"
//  "code.google.com/p/go.crypto/ssh/terminal"
//  "math/big"
//  "time"
)

const (
  RsaLowerLength = 2048
  RsaUpperLength = 4096
)

var (
  EcdsaLength = []int{224, 256, 384, 521}
)

type (
  CreateFlags struct {
    CryptType   string // rsa or ecdsa
    CryptLength int    // the bit length
    Output      string // a path or stream to output the private key to

    output_stream io.WriteCloser // the actual stream to the output
  }
)

func main() {
  if len(os.Args) == 1 {
    crash_with_help(1, "No module selected!")
  }
  switch os.Args[1] {
  case "create-private": create_private_key()
  case "create-cert-sign": create_sign_request()
  case "help": print_modules()
  case "info": info_on_file()
  case "sign": sign_request()
  }
}

// create a new private key
func create_private_key() {
  flags := parse_create_flags()

  if flags.Output == "STDOUT" {
    flags.output_stream = os.Stdout
  } else {
    var err error
    flags.output_stream, err = os.OpenFile(flags.Output, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0600)
    if err != nil {
      crash_with_help(2, fmt.Sprintf("Error when creating file %s: %s", flags.Output, err))
    }
    defer flags.output_stream.Close()
  }

  switch flags.CryptType {
    case "rsa":   create_private_key_rsa(flags)
    case "ecdsa": create_private_key_ecdsa(flags)
    default: crash_with_help(2, fmt.Sprintf("%s not supported!", flags.CryptType))
  }
}

// generate a rsa private key
func create_private_key_rsa(flags CreateFlags) {

}

// generate a ecdsa private key
func create_private_key_ecdsa(flags CreateFlags) {
  var curve elliptic.Curve
  switch flags.CryptLength {
    case 224: curve = elliptic.P224()
    case 256: curve = elliptic.P256()
    case 384: curve = elliptic.P384()
    case 521: curve = elliptic.P521()
    default: crash_with_help(2, "Unsupported crypt length!")
  }

  priv, err := ecdsa.GenerateKey(curve, rand.Reader)
  if err != nil {
    fmt.Println("Error: ", err)
    os.Exit(3)
  }
  result, err := x509.MarshalECPrivateKey(priv)
  if err != nil {
    crash_with_help(2, fmt.Sprintf("Problems marshalling the private key: %s", err))
  }
  block := &pem.Block{Type: "ECDSA PRIVATE KEY", Bytes: result}
  pem.Encode(flags.output_stream, block)
}

// parse the flags to create a private key
func parse_create_flags() CreateFlags {
  flags := CreateFlags{}
  fs := flag.NewFlagSet("create-private", flag.ExitOnError)
  fs.StringVar(&flags.CryptType, "type", "ecdsa", "which type to use to encrypt key (rsa, ecdsa)")
  fs.IntVar(&flags.CryptLength, "length", 521, fmt.Sprintf(
                      "%i - %i for rsa; %v for ecdsa", RsaLowerLength, RsaUpperLength, EcdsaLength,))
  fs.StringVar(&flags.Output, "output", "STDOUT", "filename to store the private key")
  fs.Parse(os.Args[2:])

  return flags
}

// create a sign request with a private key
func create_sign_request() {}
// get information on file (private key, sign request, certificate, ...)
func info_on_file() {}
// sign a certificate request to create a new certificate
func sign_request() {}

// print the module help
func print_modules() {
  fmt.Printf(`Usage: %s command args
where 'command' is one of:
    create-private    create a new private key
    create-cert-sign  create a new certificate sign request
    help              show this help
    info              get info on a file
    sign              sign a certificate request
`, filepath.Base(os.Args[0]))
  fmt.Println()
}

func crash_with_help(code int, message string) {
  fmt.Fprintln(os.Stderr, message)
  print_modules()
  os.Exit(code)
}

//  fmt.Println("Lets create a cert!")
//  template := &x509.Certificate{
//    SerialNumber:  big.NewInt(1),
//    Subject: pkix.Name{
//      Organization: []string{"Acme Co"},
//    },
//    NotBefore: time.Now(),
//    NotAfter: time.Now().Add(365 * 24 * time.Hour),
//    KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
//    ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
//    BasicConstraintsValid: true,
//  }
//  priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
//  fmt.Println(priv.PublicKey, err)
//  raw_string, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
//  cert, err := x509.ParseCertificate(raw_string)
//  fmt.Println(cert, err)
//
//  // read a password or so
//  password, err := terminal.ReadPassword(0)
//  fmt.Println(string(password), err)
//}
<commit_msg>add rsa private keys<commit_after>package main

import (
  "flag"
  "fmt"
  "io"
  "os"
  "path/filepath"
  "crypto/elliptic"
  "crypto/ecdsa"
  "crypto/rsa"
  "crypto/x509"
//  "crypto/x509/pkix"
  "crypto/rand"
  "encoding/pem"
//  "code.google.com/p/go.crypto/ssh/terminal"
//  "math/big"
//  "time"
)

const (
  RsaLowerLength = 2048
  RsaUpperLength = 4096
)

var (
  EcdsaLength = []int{224, 256, 384, 521}
)

type (
  CreateFlags struct {
    CryptType   string // rsa or ecdsa
    CryptLength int    // the bit length
    Output      string // a path or stream to output the private key to

    output_stream io.WriteCloser // the actual stream to the output
  }
)

func main() {
  if len(os.Args) == 1 {
    crash_with_help(1, "No module selected!")
  }
  switch os.Args[1] {
  case "create-private": create_private_key()
  case "create-cert-sign": create_sign_request()
  case "help": print_modules()
  case "info": info_on_file()
  case "sign": sign_request()
  }
}

// create a new private key
func create_private_key() {
  flags := parse_create_flags()

  if flags.Output == "STDOUT" {
    flags.output_stream = os.Stdout
  } else {
    var err error
    flags.output_stream, err = os.OpenFile(flags.Output, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0600)
    if err != nil {
      crash_with_help(2, fmt.Sprintf("Error when creating file %s: %s", flags.Output, err))
    }
    defer flags.output_stream.Close()
  }

  switch flags.CryptType {
    case "rsa":   create_private_key_rsa(flags)
    case "ecdsa": create_private_key_ecdsa(flags)
    default: crash_with_help(2, fmt.Sprintf("%s not supported!", flags.CryptType))
  }
}

// generate a rsa private key
func create_private_key_rsa(flags CreateFlags) {
  if flags.CryptLength < 2048 {
    crash_with_help(2, "Length is smaller than 2048!")
  }

  priv, err := rsa.GenerateKey( rand.Reader, flags.CryptLength)
  if err != nil {
    fmt.Fprintln(os.Stderr, "Error: ", err)
    os.Exit(3)
  }
  marshal := x509.MarshalPKCS1PrivateKey(priv)
  block := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: marshal}
  pem.Encode(flags.output_stream, block)
}

// generate a ecdsa private key
func create_private_key_ecdsa(flags CreateFlags) {
  var curve elliptic.Curve
  switch flags.CryptLength {
    case 224: curve = elliptic.P224()
    case 256: curve = elliptic.P256()
    case 384: curve = elliptic.P384()
    case 521: curve = elliptic.P521()
    default: crash_with_help(2, "Unsupported crypt length!")
  }

  priv, err := ecdsa.GenerateKey(curve, rand.Reader)
  if err != nil {
    fmt.Fprintln(os.Stderr, "Error: ", err)
    os.Exit(3)
  }
  marshal, err := x509.MarshalECPrivateKey(priv)
  if err != nil {
    crash_with_help(2, fmt.Sprintf("Problems marshalling the private key: %s", err))
  }
  block := &pem.Block{Type: "ECDSA PRIVATE KEY", Bytes: marshal}
  pem.Encode(flags.output_stream, block)
}

// parse the flags to create a private key
func parse_create_flags() CreateFlags {
  flags := CreateFlags{}
  fs := flag.NewFlagSet("create-private", flag.ExitOnError)
  fs.StringVar(&flags.CryptType, "type", "ecdsa", "which type to use to encrypt key (rsa, ecdsa)")
  fs.IntVar(&flags.CryptLength, "length", 521, fmt.Sprintf(
                      "%i - %i for rsa; %v for ecdsa", RsaLowerLength, RsaUpperLength, EcdsaLength,))
  fs.StringVar(&flags.Output, "output", "STDOUT", "filename to store the private key")
  fs.Parse(os.Args[2:])

  return flags
}

// create a sign request with a private key
func create_sign_request() {}
// get information on file (private key, sign request, certificate, ...)
func info_on_file() {}
// sign a certificate request to create a new certificate
func sign_request() {}

// print the module help
func print_modules() {
  fmt.Printf(`Usage: %s command args
where 'command' is one of:
    create-private    create a new private key
    create-cert-sign  create a new certificate sign request
    help              show this help
    info              get info on a file
    sign              sign a certificate request
`, filepath.Base(os.Args[0]))
  fmt.Println()
}

func crash_with_help(code int, message string) {
  fmt.Fprintln(os.Stderr, message)
  print_modules()
  os.Exit(code)
}

//  fmt.Println("Lets create a cert!")
//  template := &x509.Certificate{
//    SerialNumber:  big.NewInt(1),
//    Subject: pkix.Name{
//      Organization: []string{"Acme Co"},
//    },
//    NotBefore: time.Now(),
//    NotAfter: time.Now().Add(365 * 24 * time.Hour),
//    KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
//    ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
//    BasicConstraintsValid: true,
//  }
//  priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
//  fmt.Println(priv.PublicKey, err)
//  raw_string, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
//  cert, err := x509.ParseCertificate(raw_string)
//  fmt.Println(cert, err)
//
//  // read a password or so
//  password, err := terminal.ReadPassword(0)
//  fmt.Println(string(password), err)
//}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/fatih/color"
	"github.com/howeyc/fsnotify"
)

// parseArguments parses the command line flags and does interpolation
// of special formatting strings, like %f for the file name of the
// file that triggered the FileEvent.
func parseArguments(ev *fsnotify.FileEvent) (cmd string, args []string) {
	commandline := strings.Fields(flag.Args()[0])
	cmd = commandline[0]
	args = make([]string, len(commandline[1:]))

	// Do file name interpolation on the arguments if %f is in them
	for index, arg := range commandline[1:] {
		var err error
		if strings.Contains(arg, "%f") {
			arg, err = filepath.Abs(strings.Replace(arg, "%f", ev.Name, -1))
			if err != nil {
				log.Fatal("Could not get absolute path: ", err)
			}
		}
		args[index] = arg
	}

	return
}

// handle executes an event
func handle(ev *fsnotify.FileEvent, done chan bool) {
	command, args := parseArguments(ev)
	cmd := exec.Command(command, args...)

	// Set up pipes
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal("stdout not gotten: ", err)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Fatal("stderr not gotten: ", err)
	}

	// Clear the screen
	fmt.Print("\033[H\033[2J")

	// Generate the color functions
	yellow := color.New(color.FgYellow, color.Bold).SprintfFunc()
	magenta := color.New(color.FgMagenta, color.Bold).SprintfFunc()
	red := color.New(color.FgRed, color.Bold).SprintfFunc()
	green := color.New(color.FgGreen, color.Bold).SprintfFunc()

	// Print the command in nice colors
	out := fmt.Sprintf("Running %s %s...", yellow(command), magenta(strings.Join(args, " ")))
	log.Println(out)

	// Repeatedly try to start the command.
	// There are cases in which this would fail, and just looping seems to fix it.
	// This is neither nice nor elegant, but hey, it works and if it can be kept
	// simple then it should be.
	for {
		err = cmd.Start()
		if err != nil {
			log.Print("Command failed to start: ", err)
		} else {
			break
		}
	}

	// Set up channels and states for the pipe listening
	outchan := make(chan string)
	errchan := make(chan string)
	outdonechan := make(chan bool)
	errdonechan := make(chan bool)
	outdone := false

	// Trigger the pipes
	go loopOutput(outchan, outdonechan, stdout)
	go loopOutput(errchan, errdonechan, stderr)

	// Handle pipe output and wait for them to drain completely.
	for outdone == false {
		select {
		case msg := <-outchan:
			fmt.Print(msg)
		case errmsg := <-errchan:
			fmt.Print(red(errmsg))
		case <-outdonechan:
			outdone = true
		}
	}

	// Print red error message or green success message
	if err = cmd.Wait(); err != nil {
		log.Println(red(err.Error()))
	} else {
		log.Println(green("Execution successful."))
	}

	done <- true
}

// loopOutput takes a pipe and drains it until EOF.
func loopOutput(c chan string, done chan bool, pipe io.ReadCloser) {
	buf := make([]byte, 1024)

	for {
		n, err := pipe.Read(buf)

		// Either if the pipe was empty or an EOF or other error was returned.
		if n == 0 && err == nil || err != nil {
			done <- true
			return
		}

		c <- string(buf[:n])
	}
}

func main() {
	dir := flag.String("d", ".", "directory to watch")
	flag.Parse()

	if flag.NArg() != 1 {
		log.Fatal("One command line argument sting required.")
	}

	watcher, err := fsnotify.NewWatcher()
	defer watcher.Close()

	if err != nil {
		log.Fatal("Unable to create fsnotify watcher: ", err)
	}

	done := make(chan bool)
	item := make(chan bool)

	// Process events
	go func() {
		running := false
		for {
			select {
			case ev := <-watcher.Event:
				// A watcher event arrived - act on it, but only if
				// no other action is already happening
				if running == false {
					running = true
					go handle(ev, item)
				}

			case <-item:
				// The runner has returned! Let the others roam!
				running = false

			case err := <-watcher.Error:
				log.Println("watcher error: ", err)

			}
		}
	}()

	log.Printf("Watching %s...", *dir)
	err = watcher.Watch(*dir)
	if err != nil {
		log.Fatal("Directory watching failed: ", err)
	}

	<-done
}
<commit_msg>Add option to surpress decorative messages<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/fatih/color"
	"github.com/howeyc/fsnotify"
)

// parseArguments parses the command line flags and does interpolation
// of special formatting strings, like %f for the file name of the
// file that triggered the FileEvent.
func parseArguments(ev *fsnotify.FileEvent) (cmd string, args []string) {
	commandline := strings.Fields(flag.Args()[0])
	cmd = commandline[0]
	args = make([]string, len(commandline[1:]))

	// Do file name interpolation on the arguments if %f is in them
	for index, arg := range commandline[1:] {
		var err error
		if strings.Contains(arg, "%f") {
			arg, err = filepath.Abs(strings.Replace(arg, "%f", ev.Name, -1))
			if err != nil {
				log.Fatal("Could not get absolute path: ", err)
			}
		}
		args[index] = arg
	}

	return
}

// handle executes an event
func handle(ev *fsnotify.FileEvent, done chan bool, quiet bool) {
	command, args := parseArguments(ev)
	cmd := exec.Command(command, args...)

	// Set up pipes
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal("stdout not gotten: ", err)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Fatal("stderr not gotten: ", err)
	}

	// Clear the screen
	fmt.Print("\033[H\033[2J")

	// Generate the color functions
	yellow := color.New(color.FgYellow, color.Bold).SprintfFunc()
	magenta := color.New(color.FgMagenta, color.Bold).SprintfFunc()
	red := color.New(color.FgRed, color.Bold).SprintfFunc()
	green := color.New(color.FgGreen, color.Bold).SprintfFunc()

	// Print the command in nice colors
	if quiet == false {
		out := fmt.Sprintf("Running %s %s...", yellow(command), magenta(strings.Join(args, " ")))
		log.Println(out)
	}

	// Repeatedly try to start the command.
	// There are cases in which this would fail, and just looping seems to fix it.
	// This is neither nice nor elegant, but hey, it works and if it can be kept
	// simple then it should be.
	for {
		err = cmd.Start()
		if err != nil {
			log.Print("Command failed to start: ", err)
		} else {
			break
		}
	}

	// Set up channels and states for the pipe listening
	outchan := make(chan string)
	errchan := make(chan string)
	outdonechan := make(chan bool)
	errdonechan := make(chan bool)
	outdone := false

	// Trigger the pipes
	go loopOutput(outchan, outdonechan, stdout)
	go loopOutput(errchan, errdonechan, stderr)

	// Handle pipe output and wait for them to drain completely.
	for outdone == false {
		select {
		case msg := <-outchan:
			fmt.Print(msg)
		case errmsg := <-errchan:
			fmt.Print(red(errmsg))
		case <-outdonechan:
			outdone = true
		}
	}

	// Print red error message or green success message
	if err = cmd.Wait(); err != nil {
		log.Println(red(err.Error()))
	} else {
		if quiet == false {
			log.Println(green("Execution successful."))
		}
	}

	done <- true
}

// loopOutput takes a pipe and drains it until EOF.
func loopOutput(c chan string, done chan bool, pipe io.ReadCloser) {
	buf := make([]byte, 1024)

	for {
		n, err := pipe.Read(buf)

		// Either if the pipe was empty or an EOF or other error was returned.
		if n == 0 && err == nil || err != nil {
			done <- true
			return
		}

		c <- string(buf[:n])
	}
}

func main() {
	dir := flag.String("d", ".", "directory to watch")
	quiet := flag.Bool("q", false, "Supress start and stop surroundings")
	flag.Parse()

	if flag.NArg() != 1 {
		log.Fatal("One command line argument sting required.")
	}

	watcher, err := fsnotify.NewWatcher()
	defer watcher.Close()

	if err != nil {
		log.Fatal("Unable to create fsnotify watcher: ", err)
	}

	done := make(chan bool)
	item := make(chan bool)

	// Process events
	go func() {
		running := false
		for {
			select {
			case ev := <-watcher.Event:
				// A watcher event arrived - act on it, but only if
				// no other action is already happening
				if running == false {
					running = true
					go handle(ev, item, *quiet)
				}

			case <-item:
				// The runner has returned! Let the others roam!
				running = false

			case err := <-watcher.Error:
				log.Println("watcher error: ", err)

			}
		}
	}()

	log.Printf("Watching %s...", *dir)
	err = watcher.Watch(*dir)
	if err != nil {
		log.Fatal("Directory watching failed: ", err)
	}

	<-done
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"runtime"
)

const CACHECTL_VERSION = "0.0.1"

func printCachectlVersion() {
	fmt.Printf(`cachectl %s
Compiler: %s %s
Copyright (C) 2014 Tatsuhiko Kubo <cubicdaiya@gmail.com>
`,
		CACHECTL_VERSION,
		runtime.Compiler,
		runtime.Version())
}

func printCacheStat(fpath string, fsize int64) {
	pagesize := os.Getpagesize()
	pagesizeKB := pagesize / 1024
	if fsize == 0 {
		fmt.Printf("%s 's pages in cache: %d/%d (%.1f%%) [filesize=%.1fK, pagesize=%dK]\n", fpath, 0, 0, 0.0, 0.0, pagesizeKB)
	}

	pages := (fsize + int64(pagesize) - 1) / int64(pagesize)
	pagesActive := C.activePages(C.CString(fpath))
	activeRate := 100.0 * (float64(pagesActive) / float64(pages))
	filesizeKB := float64(fsize) / 1024
	fmt.Printf("%s 's pages in cache: %d/%d (%.1f%%)  [filesize=%.1fK, pagesize=%dK]\n",
		fpath, pagesActive, pages, activeRate, filesizeKB, pagesizeKB)
}

func deleteCache(fpath string, fsize int64, rate float64) error {
	if rate < 0.0 || rate > 1.0 {
		return errors.New(fmt.Sprintf("%f: rate should be less than 1.0\n", rate))
	}

	result := C.fadvise(C.CString(fpath), C.float(rate))
	if result == -1 {
		return errors.New(fmt.Sprintf("failed to delete page cache for %s", fpath))
	}

	return nil
}

func main() {

	// Parse flags
	version := flag.Bool("v", false, "show version")
	op := flag.String("op", "stat", "operation(stat, del)")
	fpath := flag.String("f", "", "target file path")
	rate := flag.Float64("r", 1.0, "rate of page cache deleted(0.0 <= r<= 1.0)")
	flag.Parse()

	if *version {
		printCachectlVersion()
		os.Exit(0)
	}

	if *fpath == "" {
		fmt.Println("target file path is empty.")
		os.Exit(0)
	}

	fi, err := os.Stat(*fpath)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}

	if !fi.Mode().IsRegular() {
		fmt.Printf("%s is not regular file\n", fi.Name())
		os.Exit(1)
	}

	if *op == "stat" {
		printCacheStat(*fpath, fi.Size())
	} else {
		fmt.Printf("Before deleting %s 's page cache\n\n", *fpath)
		printCacheStat(*fpath, fi.Size())

		deleteCache(*fpath, fi.Size(), *rate)

		fmt.Printf("\nAfter deleting %s 's page cache\n\n", *fpath)
		printCacheStat(*fpath, fi.Size())
	}

}
<commit_msg>forgot to add "C".<commit_after>package main

import (
	"C"
	"errors"
	"flag"
	"fmt"
	"os"
	"runtime"
)

const CACHECTL_VERSION = "0.0.1"

func printCachectlVersion() {
	fmt.Printf(`cachectl %s
Compiler: %s %s
Copyright (C) 2014 Tatsuhiko Kubo <cubicdaiya@gmail.com>
`,
		CACHECTL_VERSION,
		runtime.Compiler,
		runtime.Version())
}

func printCacheStat(fpath string, fsize int64) {
	pagesize := os.Getpagesize()
	pagesizeKB := pagesize / 1024
	if fsize == 0 {
		fmt.Printf("%s 's pages in cache: %d/%d (%.1f%%) [filesize=%.1fK, pagesize=%dK]\n", fpath, 0, 0, 0.0, 0.0, pagesizeKB)
	}

	pages := (fsize + int64(pagesize) - 1) / int64(pagesize)
	pagesActive := C.activePages(C.CString(fpath))
	activeRate := 100.0 * (float64(pagesActive) / float64(pages))
	filesizeKB := float64(fsize) / 1024
	fmt.Printf("%s 's pages in cache: %d/%d (%.1f%%)  [filesize=%.1fK, pagesize=%dK]\n",
		fpath, pagesActive, pages, activeRate, filesizeKB, pagesizeKB)
}

func deleteCache(fpath string, fsize int64, rate float64) error {
	if rate < 0.0 || rate > 1.0 {
		return errors.New(fmt.Sprintf("%f: rate should be less than 1.0\n", rate))
	}

	result := C.fadvise(C.CString(fpath), C.float(rate))
	if result == -1 {
		return errors.New(fmt.Sprintf("failed to delete page cache for %s", fpath))
	}

	return nil
}

func main() {

	// Parse flags
	version := flag.Bool("v", false, "show version")
	op := flag.String("op", "stat", "operation(stat, del)")
	fpath := flag.String("f", "", "target file path")
	rate := flag.Float64("r", 1.0, "rate of page cache deleted(0.0 <= r<= 1.0)")
	flag.Parse()

	if *version {
		printCachectlVersion()
		os.Exit(0)
	}

	if *fpath == "" {
		fmt.Println("target file path is empty.")
		os.Exit(0)
	}

	fi, err := os.Stat(*fpath)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}

	if !fi.Mode().IsRegular() {
		fmt.Printf("%s is not regular file\n", fi.Name())
		os.Exit(1)
	}

	if *op == "stat" {
		printCacheStat(*fpath, fi.Size())
	} else {
		fmt.Printf("Before deleting %s 's page cache\n\n", *fpath)
		printCacheStat(*fpath, fi.Size())

		deleteCache(*fpath, fi.Size(), *rate)

		fmt.Printf("\nAfter deleting %s 's page cache\n\n", *fpath)
		printCacheStat(*fpath, fi.Size())
	}

}
<|endoftext|>


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

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	luis "github.com/kkdai/luis"
	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client
var luisAction *LuisAction
var allIntents *luis.IntentListResponse

func main() {
	var err error
	appID := os.Getenv("APP_ID")
	apiKey := os.Getenv("APP_KEY")
	log.Println("Luis:", appID, apiKey)
	// luisAction = NewLuisAction(appID, apiKey)
	// res, err2 := luisAction.LuisAPI.IntentList()
	l := luis.NewLuis(apiKey, appID)
	res, err2 := l.IntentList()

	log.Println(res, err2)

	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch event.Message.(type) {
			case *linebot.TextMessage:
				// if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(message.ID+":"+message.Text+" OK!")).Do(); err != nil {
				// 	log.Print(err)
				// }

				res, err := luisAction.GetIntents()
				if err != nil {
					log.Println(err)
				}

				var intentList []string
				log.Println("All intent:", *res)
				for _, v := range *res {
					intentList = append(intentList, v.Name)
				}

				ListAllIntents(bot, event.ReplyToken, intentList)
			}
		}
	}
}

//ListAllIntents :
func ListAllIntents(bot *linebot.Client, replyToken string, intents []string) {

	// var buttons []linebot.TemplateAction

	// for _, v := range intents {
	// 	buttons = append(buttons, linebot.NewPostbackTemplateAction(v, v, ""))
	// }

	// linebot.NewURITemplateAction("Go to line.me", "https://line.me"),
	// linebot.NewPostbackTemplateAction("Say hello1", "hello こんにちは", ""),

	template := linebot.NewButtonsTemplate("", "My button sample", "Hello, my button",
		linebot.NewPostbackTemplateAction(intents[0], intents[0], ""),
		linebot.NewPostbackTemplateAction(intents[1], intents[1], ""),
		linebot.NewPostbackTemplateAction(intents[2], intents[2], ""),
		linebot.NewPostbackTemplateAction(intents[3], intents[3], ""))

	if _, err := bot.ReplyMessage(
		replyToken,
		linebot.NewTemplateMessage("Buttons alt text", template)).Do(); err != nil {
		log.Print(err)
	}
}
<commit_msg>no message<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	luis "github.com/kkdai/luis"
	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client
var luisAction *LuisAction
var allIntents *luis.IntentListResponse

func main() {
	var err error
	appID := os.Getenv("APP_ID")
	apiKey := os.Getenv("APP_KEY")
	log.Println("Luis:", appID, apiKey)
	// luisAction = NewLuisAction(appID, apiKey)
	// res, err2 := luisAction.LuisAPI.IntentList()
	l := luis.NewLuis(apiKey, appID)
	res, err2 := l.IntentList()
	result := luis.NewIntentListResponse(res)

	log.Println(result, res, err2)

	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch event.Message.(type) {
			case *linebot.TextMessage:
				// if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(message.ID+":"+message.Text+" OK!")).Do(); err != nil {
				// 	log.Print(err)
				// }

				res, err := luisAction.GetIntents()
				if err != nil {
					log.Println(err)
				}

				var intentList []string
				log.Println("All intent:", *res)
				for _, v := range *res {
					intentList = append(intentList, v.Name)
				}

				ListAllIntents(bot, event.ReplyToken, intentList)
			}
		}
	}
}

//ListAllIntents :
func ListAllIntents(bot *linebot.Client, replyToken string, intents []string) {

	// var buttons []linebot.TemplateAction

	// for _, v := range intents {
	// 	buttons = append(buttons, linebot.NewPostbackTemplateAction(v, v, ""))
	// }

	// linebot.NewURITemplateAction("Go to line.me", "https://line.me"),
	// linebot.NewPostbackTemplateAction("Say hello1", "hello こんにちは", ""),

	template := linebot.NewButtonsTemplate("", "My button sample", "Hello, my button",
		linebot.NewPostbackTemplateAction(intents[0], intents[0], ""),
		linebot.NewPostbackTemplateAction(intents[1], intents[1], ""),
		linebot.NewPostbackTemplateAction(intents[2], intents[2], ""),
		linebot.NewPostbackTemplateAction(intents[3], intents[3], ""))

	if _, err := bot.ReplyMessage(
		replyToken,
		linebot.NewTemplateMessage("Buttons alt text", template)).Do(); err != nil {
		log.Print(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/byrnedo/dockdash/dockerClient"
	goDocker "github.com/fsouza/go-dockerclient"
	ui "github.com/gizak/termui"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
)

type DockerInfoType int

const (
	ImageInfo DockerInfoType = iota
	PortInfo
	VolumesInfo
	TimeInfo
)

var InfoHeaders map[DockerInfoType]string = map[DockerInfoType]string{
	ImageInfo:   "Images",
	PortInfo:    "Ports",
	VolumesInfo: "Volumes",
	TimeInfo:    "Created At",
}

const MaxContainers = 1000
const MaxHorizPosition = int(TimeInfo)

var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

func mapValuesSorted(mapToSort map[string]*goDocker.Container) (sorted []*goDocker.Container) {

	sorted = make([]*goDocker.Container, len(mapToSort))
	var keys []string
	for k := range mapToSort {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// To perform the opertion you want
	count := 0
	for _, k := range keys {
		sorted[count] = mapToSort[k]
		count++
	}
	return
}

func InitLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer) {

	Trace = log.New(traceHandle,
		"TRACE: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Info = log.New(infoHandle,
		"INFO: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Warning = log.New(warningHandle,
		"WARNING: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Error = log.New(errorHandle,
		"ERROR: ",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func createExitBar() (p *ui.Par) {
	p = ui.NewPar(":PRESS q TO QUIT")
	p.Height = 3
	p.TextFgColor = ui.ColorWhite
	p.Border.Label = "Text Box"
	p.Border.FgColor = ui.ColorCyan
	return
}

func createErrorBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorRed
	p.HasBorder = false
	return
}

func createStatusBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorGreen
	p.HasBorder = true
	return
}

func createCPUGauge() *ui.Gauge {
	cpuGauge := ui.NewGauge()
	cpuGauge.Percent = 50
	cpuGauge.Height = 3
	cpuGauge.Border.Label = "CPU Usage"
	cpuGauge.BarColor = ui.ColorRed
	cpuGauge.Border.FgColor = ui.ColorWhite
	cpuGauge.Border.LabelFgColor = ui.ColorCyan
	return cpuGauge
}

func createMemGauge() *ui.Gauge {
	memGauge := ui.NewGauge()
	memGauge.Percent = 50
	memGauge.Height = 3
	memGauge.Border.Label = "Mem. Usage"
	memGauge.BarColor = ui.ColorRed
	memGauge.Border.FgColor = ui.ColorWhite
	memGauge.Border.LabelFgColor = ui.ColorCyan
	return memGauge
}

func createContainerList() *ui.List {
	list := ui.NewList()
	list.ItemFgColor = ui.ColorYellow
	list.HasBorder = true
	return list
}

func createDockerLineChart() *ui.LineChart {
	lc := ui.NewLineChart()
	lc.Border.Label = "Container Numbers"
	//lc.Data = sinps
	lc.Height = 10
	lc.AxesColor = ui.ColorWhite
	lc.LineColor = ui.ColorRed | ui.AttrBold
	lc.Mode = "line"
	return lc
}

func createPortsString(ports map[goDocker.Port][]goDocker.PortBinding) (portsStr string) {

	for intPort, extHostPortList := range ports {
		if len(extHostPortList) == 0 {
			portsStr += intPort.Port() + "->N/A,"
		}
		for _, extHostPort := range extHostPortList {
			portsStr += intPort.Port() + "->" + extHostPort.HostIP + ":" + extHostPort.HostPort + ","
		}
	}
	return strings.TrimLeft(portsStr, ",")
}

func getNameAndInfoOfContainers(containers map[string]*goDocker.Container, offset int, infoType DockerInfoType) ([]string, []string) {
	if offset > len(containers) {
		offset = len(containers) - 1
	}

	numContainersSubset := len(containers) - offset

	names := make([]string, numContainersSubset)
	info := make([]string, numContainersSubset)

	containersSorted := mapValuesSorted(containers)
	for index, cont := range containersSorted {
		if index < offset {
			continue
		}

		names[index-offset] = strings.TrimLeft(cont.Name, "/")
		switch infoType {
		case ImageInfo:
			info[index-offset] = strings.Replace(cont.Config.Image, "dockerregistry.pagero.local", "d.p.l", 1)
		case PortInfo:
			Info.Println("Creating list of", len(cont.NetworkSettings.Ports), "ports")
			info[index-offset] = createPortsString(cont.NetworkSettings.Ports)
		case VolumesInfo:
			Info.Println("Creating list of", len(cont.Volumes), "volumes")
			volStr := ""
			for intVol, hostVol := range cont.Volumes {
				volStr += intVol + ":" + hostVol + ","
			}
			info[index-offset] = strings.TrimRight(volStr, ",")
		case TimeInfo:
			info[index-offset] = cont.Created.String()
		default:
			Error.Println("Unhandled info type", infoType)
		}
	}
	return names, info
}

func updateContainerList(rightList *ui.List, leftList *ui.List, containers map[string]*goDocker.Container, offset int, horizPosition DockerInfoType) {
	names, info := getNameAndInfoOfContainers(containers, offset, horizPosition)
	rightList.Height = len(containers) + 2
	leftList.Height = len(containers) + 2
	rightList.Items = names
	leftList.Border.Label = InfoHeaders[horizPosition]
	leftList.Items = info
}

/*
 *func updateStatisticsRoutines(cl *dockerClient.DockerClient, event *goDocker.APIEvents, deadContainerChan chan<- string, startedContainerChan chan<- string, statsChan chan *goDocker.Stats, errChan chan<- string) {
 *    switch event.Status {
 *    case "die":
 *        go stopGettingStats(cl, event.ID, errChan)
 *    case "start":
 *        go startGettingStats(cl, event.ID, statsChan, errChan)
 *    }
 *}
 *
 *func startGettingStats(cl *dockerClient.DockerClient, id string, statsChan chan *goDocker.Stats, errChan chan<- string) {
 *    if err := cl.Stats(goDocker.StatsOptions{id, statsChan, true, nil, 0}); err != nil {
 *        errChan <- err.Error()
 *    }
 *}
 *
 *func stopGettingStats(cl *dockerClient.DockerClient, id string, errChan chan<- string) {
 *
 *}
 */

func main() {
	logPath := "/tmp/dockdash.log"
	file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic("Failed to open log file " + logPath + ":" + err.Error())
	}

	InitLog(ioutil.Discard, file, file, file)

	docker, err := dockerClient.NewDockerClient()
	if err != nil {
		panic(err)
	}

	err = ui.Init()
	if err != nil {
		panic(err)
	}

	defer ui.Close()

	exitBar := createExitBar()
	errorBar := createErrorBar()
	statusBar := createStatusBar()

	containerListLeft := createContainerList()
	containerListLeft.Border.Label = "Name"
	containerListRight := createContainerList()
	containerListRight.Border.Label = "Image"

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(12, 0, exitBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, errorBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, statusBar),
		),
		ui.NewRow(
			ui.NewCol(3, 0, containerListLeft),
			ui.NewCol(9, 0, containerListRight),
		),
	)

	// calculate layout
	ui.Body.Align()

	drawChan := make(chan bool)
	/*
	 *errChan := make(chan string, 10)
	 */
	dockerEventChan := make(chan *goDocker.APIEvents, 10)
	containersChan := make(chan map[string]*goDocker.Container, 10)
	listStartOffsetChan := make(chan int)
	horizPositionChan := make(chan int)
	maxOffsetChan := make(chan int)
	deadContainerChan := make(chan string, 10)
	startedContainerChan := make(chan string, 10)
	doneChan := make(chan bool)
	evtChan := ui.EventCh()
	/*
	 *statsChan := make(chan *goDocker.Stats)
	 */

	err = docker.AddEventListener(dockerEventChan)
	if err != nil {
		panic("Failed to add event listener: " + err.Error())
	}

	defer func() {
		if err := docker.RemoveEventListener(dockerEventChan); err != nil {
			panic(err)
		}
	}()

	uiRoutine := func() {
		var horizPosition int = 0
		var offset int = 0
		var maxOffset int = 0
		for {
			select {
			case e := <-evtChan:
				Info.Println("Got ui event:", e)
				if e.Type == ui.EventKey {
					switch e.Ch {
					case 'q':
						doneChan <- true
					case 0:
						switch e.Key {
						case ui.KeyArrowLeft:
							if horizPosition > 0 {
								horizPosition--
							}
							horizPositionChan <- horizPosition
						case ui.KeyArrowRight:
							if horizPosition < MaxHorizPosition {
								horizPosition++
							}
							horizPositionChan <- horizPosition
						case ui.KeyArrowDown:
							if offset < maxOffset && offset < MaxContainers {
								offset++
							}
							listStartOffsetChan <- offset
							//shift the list down
						case ui.KeyArrowUp:
							if offset > 0 {
								offset--
							}
							listStartOffsetChan <- offset
							//shift the list up
						default:
							Info.Printf("Got unhandled key %d\n", e.Key)
						}
					}
				}
				if e.Type == ui.EventResize {
					ui.Body.Width = ui.TermWidth()
					ui.Body.Align()
				}
			case max := <-maxOffsetChan:
				maxOffset = max
			case _ = <-drawChan:
				Info.Println("Got draw event")
				ui.Render(ui.Body)
			}
		}
	}
	go uiRoutine()

	Info.Println("Sending initial draw signal")

	//handle container addition/removal
	Info.Println("Spinning off container change routine")
	containerChangeRoutine := func() {
		currentContainers := make(map[string]*goDocker.Container)
		for {
			select {
			case newContainerID := <-startedContainerChan:
				Info.Println("Got new container event")
				cont, err := docker.InspectContainer(newContainerID)
				if err != nil {
					Error.Println("Failed to inspect new container", newContainerID, ":", err)
					continue
				}
				currentContainers[cont.ID] = cont
				maxOffsetChan <- len(currentContainers) - 1
				containersChan <- currentContainers
			case removedContainerID := <-deadContainerChan:
				Info.Println("Got dead container event")
				delete(currentContainers, removedContainerID)
				maxOffsetChan <- len(currentContainers) - 1
				containersChan <- currentContainers
			}
		}
	}
	go containerChangeRoutine()

	Info.Println("Spinning off update widgets routine")
	updateWidgets := func() {
		lastContainersList := make(map[string]*goDocker.Container)
		offset := 0
		horizPosition := 0
		for {
			select {
			case hp := <-horizPositionChan:
				horizPosition = hp
				Info.Println("Got changed horiz position", horizPosition)
				updateContainerList(containerListLeft, containerListRight, lastContainersList, offset, DockerInfoType(horizPosition))
				drawChan <- true
			case containers := <-containersChan:
				Info.Println("Got containers changed event")
				updateContainerList(containerListLeft, containerListRight, containers, offset, DockerInfoType(horizPosition))
				lastContainersList = containers
				drawChan <- true
			case offset = <-listStartOffsetChan:
				Info.Println("Got list offset of", offset)
				updateContainerList(containerListLeft, containerListRight, lastContainersList, offset, DockerInfoType(horizPosition))
				drawChan <- true
			}
		}
	}
	go updateWidgets()

	dockerEventRouting := func() {
		for {
			select {
			case e := <-dockerEventChan:
				switch e.Status {
				case "start":
					startedContainerChan <- e.ID
				case "die":
					deadContainerChan <- e.ID
				}
			}
		}
	}

	go dockerEventRouting()

	//setup initial containers
	containers, _ := docker.ListContainers(goDocker.ListContainersOptions{})
	drawChan <- true
	Info.Println("Listing intial", len(containers), "containers as started")
	for _, cont := range containers {
		startedContainerChan <- cont.ID
	}

	<-doneChan

}
<commit_msg>Stats handling<commit_after>package main

import (
	"github.com/byrnedo/dockdash/dockerClient"
	goDocker "github.com/fsouza/go-dockerclient"
	ui "github.com/gizak/termui"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
)

type DockerInfoType int

const (
	ImageInfo DockerInfoType = iota
	PortInfo
	VolumesInfo
	TimeInfo
)

var InfoHeaders map[DockerInfoType]string = map[DockerInfoType]string{
	ImageInfo:   "Images",
	PortInfo:    "Ports",
	VolumesInfo: "Volumes",
	TimeInfo:    "Created At",
}

const MaxContainers = 1000
const MaxHorizPosition = int(TimeInfo)

type StatsResult struct {
	ID    string
	Stats *goDocker.Stats
}

var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

func mapValuesSorted(mapToSort map[string]*goDocker.Container) (sorted []*goDocker.Container) {

	sorted = make([]*goDocker.Container, len(mapToSort))
	var keys []string
	for k := range mapToSort {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// To perform the opertion you want
	var count int
	for _, k := range keys {
		sorted[count] = mapToSort[k]
		count++
	}
	return
}

func InitLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer) {

	Trace = log.New(traceHandle,
		"TRACE: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Info = log.New(infoHandle,
		"INFO: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Warning = log.New(warningHandle,
		"WARNING: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Error = log.New(errorHandle,
		"ERROR: ",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func createExitBar() (p *ui.Par) {
	p = ui.NewPar(":PRESS q TO QUIT")
	p.Height = 3
	p.TextFgColor = ui.ColorWhite
	p.Border.Label = "Text Box"
	p.Border.FgColor = ui.ColorCyan
	return
}

func createErrorBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorRed
	p.HasBorder = false
	return
}

func createStatusBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorGreen
	p.HasBorder = true
	return
}

func createCPUGauge() *ui.Gauge {
	cpuGauge := ui.NewGauge()
	cpuGauge.Percent = 50
	cpuGauge.Height = 3
	cpuGauge.Border.Label = "CPU Usage"
	cpuGauge.BarColor = ui.ColorRed
	cpuGauge.Border.FgColor = ui.ColorWhite
	cpuGauge.Border.LabelFgColor = ui.ColorCyan
	return cpuGauge
}

func createMemGauge() *ui.Gauge {
	memGauge := ui.NewGauge()
	memGauge.Percent = 50
	memGauge.Height = 3
	memGauge.Border.Label = "Mem. Usage"
	memGauge.BarColor = ui.ColorRed
	memGauge.Border.FgColor = ui.ColorWhite
	memGauge.Border.LabelFgColor = ui.ColorCyan
	return memGauge
}

func createContainerList() *ui.List {
	list := ui.NewList()
	list.ItemFgColor = ui.ColorYellow
	list.HasBorder = true
	return list
}

func createDockerLineChart() *ui.LineChart {
	lc := ui.NewLineChart()
	lc.Border.Label = "Container Numbers"
	//lc.Data = sinps
	lc.Height = 10
	lc.AxesColor = ui.ColorWhite
	lc.LineColor = ui.ColorRed | ui.AttrBold
	lc.Mode = "line"
	return lc
}

func createPortsString(ports map[goDocker.Port][]goDocker.PortBinding) (portsStr string) {

	for intPort, extHostPortList := range ports {
		if len(extHostPortList) == 0 {
			portsStr += intPort.Port() + "->N/A,"
		}
		for _, extHostPort := range extHostPortList {
			portsStr += intPort.Port() + "->" + extHostPort.HostIP + ":" + extHostPort.HostPort + ","
		}
	}
	return strings.TrimLeft(portsStr, ",")
}

func getNameAndInfoOfContainers(containers map[string]*goDocker.Container, offset int, infoType DockerInfoType) ([]string, []string) {
	if offset > len(containers) {
		offset = len(containers) - 1
	}

	numContainersSubset := len(containers) - offset

	names := make([]string, numContainersSubset)
	info := make([]string, numContainersSubset)

	containersSorted := mapValuesSorted(containers)
	for index, cont := range containersSorted {
		if index < offset {
			continue
		}

		names[index-offset] = cont.ID[:12] + " " + strings.TrimLeft(cont.Name, "/")
		switch infoType {
		case ImageInfo:
			info[index-offset] = strings.Replace(cont.Config.Image, "dockerregistry.pagero.local", "d.p.l", 1)
		case PortInfo:
			info[index-offset] = createPortsString(cont.NetworkSettings.Ports)
		case VolumesInfo:
			volStr := ""
			for intVol, hostVol := range cont.Volumes {
				volStr += intVol + ":" + hostVol + ","
			}
			info[index-offset] = strings.TrimRight(volStr, ",")
		case TimeInfo:
			info[index-offset] = cont.Created.String()
		default:
			Error.Println("Unhandled info type", infoType)
		}
	}
	return names, info
}

func updateContainerList(leftList *ui.List, rightList *ui.List, containers map[string]*goDocker.Container, offset int, horizPosition DockerInfoType) {
	names, info := getNameAndInfoOfContainers(containers, offset, horizPosition)
	leftList.Height = len(containers) + 2
	rightList.Height = len(containers) + 2
	leftList.Items = names
	rightList.Border.Label = InfoHeaders[horizPosition]
	rightList.Items = info
}

func updateStatsBarChart(statsChart *ui.BarChart, statsList map[string]*goDocker.Stats) {

	statsChart.DataLabels = make([]string, len(statsList))
	statsChart.Data = make([]int, len(statsList))
	count := 0
	for key, nums := range statsList {
		Info.Printf("%+v", nums)
		statsChart.DataLabels[count] = key[:2]
		statsChart.Data[count] = int(nums.CPUStats.CPUUsage.TotalUsage)
		count++
	}
}

func main() {
	logPath := "/tmp/dockdash.log"
	file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic("Failed to open log file " + logPath + ":" + err.Error())
	}

	InitLog(ioutil.Discard, file, file, file)

	docker, err := dockerClient.NewDockerClient()
	if err != nil {
		panic(err)
	}

	err = ui.Init()
	if err != nil {
		panic(err)
	}

	defer ui.Close()

	exitBar := createExitBar()
	errorBar := createErrorBar()

	containerListLeft := createContainerList()
	containerListLeft.Border.Label = "Name"
	containerListRight := createContainerList()
	containerListRight.Border.Label = "Image"

	statsChart := ui.NewBarChart()
	statsChart.Height = 10

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(12, 0, exitBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, statsChart),
		),
		ui.NewRow(
			ui.NewCol(12, 0, errorBar),
		),
		ui.NewRow(
			ui.NewCol(3, 0, containerListLeft),
			ui.NewCol(9, 0, containerListRight),
		),
	)

	// calculate layout
	ui.Body.Align()

	drawChan := make(chan bool)
	/*
	 *errChan := make(chan string, 10)
	 */
	dockerEventChan := make(chan *goDocker.APIEvents, 10)
	containersChan := make(chan map[string]*goDocker.Container)
	listStartOffsetChan := make(chan int)
	horizPositionChan := make(chan int)
	maxOffsetChan := make(chan int)
	deadContainerChan := make(chan string)
	startedContainerChan := make(chan string)
	doneChan := make(chan bool)
	uiEventChan := ui.EventCh()

	// Statistics
	startGatheringStatisticsChan := make(chan string)
	stopGatheringStatisticsChan := make(chan string)

	statsResultsChan := make(chan *StatsResult)
	statsResultsDoneChan := make(chan string)

	err = docker.AddEventListener(dockerEventChan)
	if err != nil {
		panic("Failed to add event listener: " + err.Error())
	}

	defer func() {
		if err := docker.RemoveEventListener(dockerEventChan); err != nil {
			panic(err)
		}
	}()

	statsRenderingRoutine := func() {
		statsList := make(map[string]*goDocker.Stats)
		for {
			select {
			case msg := <-statsResultsChan:
				statsList[msg.ID] = msg.Stats
				updateStatsBarChart(statsChart, statsList)
				drawChan <- true
			case id := <-statsResultsDoneChan:
				delete(statsList, id)
				updateStatsBarChart(statsChart, statsList)
				drawChan <- true
			}
		}
	}
	go statsRenderingRoutine()

	statsHandlingRoutine := func() {
		statsDoneChannels := make(map[string]chan bool)
		startsResultInterceptChannels := make(map[string]chan *goDocker.Stats)
		startsResultInterceptDoneChannels := make(map[string]chan bool)
		for {
			select {
			case id := <-startGatheringStatisticsChan:
				statsDoneChannels[id] = make(chan bool, 1)
				startsResultInterceptChannels[id] = make(chan *goDocker.Stats)
				startsResultInterceptDoneChannels[id] = make(chan bool)
				spinOffStatsInterceptor := func() {
					for {
						select {
						case stat := <-startsResultInterceptChannels[id]:
							statsResultsChan <- &StatsResult{id, stat}
						case _ = <-startsResultInterceptDoneChannels[id]:
							return
						}
					}
				}
				go spinOffStatsInterceptor()
				Info.Println("Starting stats routine for", id)
				spinOffStatsListener := func() {
					if err := docker.Stats(goDocker.StatsOptions{id, startsResultInterceptChannels[id], true, statsDoneChannels[id], 0}); err != nil {
						Error.Println("Error starting statistics handler for id", id, ":", err.Error())
						startsResultInterceptDoneChannels[id] <- true
						close(statsDoneChannels[id])
						close(startsResultInterceptChannels[id])
						delete(statsDoneChannels, id)
						delete(startsResultInterceptChannels, id)
						statsResultsDoneChan <- id
					}
				}
				go spinOffStatsListener()
			case id := <-stopGatheringStatisticsChan:
				Info.Println("Stopping stats routine for", id)
				statsDoneChannels[id] <- true
				startsResultInterceptDoneChannels[id] <- true
				close(statsDoneChannels[id])
				close(startsResultInterceptChannels[id])
				delete(statsDoneChannels, id)
				delete(startsResultInterceptChannels, id)
				statsResultsDoneChan <- id
			}
		}
	}
	go statsHandlingRoutine()

	uiRoutine := func() {
		var horizPosition int = 0
		var offset int = 0
		var maxOffset int = 0
		for {
			select {
			case e := <-uiEventChan:
				Info.Println("Got ui event:", e)
				if e.Type == ui.EventKey {
					switch e.Ch {
					case 'q':
						doneChan <- true
					case 0:
						switch e.Key {
						case ui.KeyArrowLeft:
							if horizPosition > 0 {
								horizPosition--
							}
							horizPositionChan <- horizPosition
						case ui.KeyArrowRight:
							if horizPosition < MaxHorizPosition {
								horizPosition++
							}
							horizPositionChan <- horizPosition
						case ui.KeyArrowDown:
							if offset < maxOffset && offset < MaxContainers {
								offset++
							}
							listStartOffsetChan <- offset
							//shift the list down
						case ui.KeyArrowUp:
							if offset > 0 {
								offset--
							}
							listStartOffsetChan <- offset
							//shift the list up
						default:
							Info.Printf("Got unhandled key %d\n", e.Key)
						}
					}
				}
				if e.Type == ui.EventResize {
					ui.Body.Width = ui.TermWidth()
					ui.Body.Align()
				}
			case max := <-maxOffsetChan:
				maxOffset = max
			case _ = <-drawChan:
				Info.Println("Got draw event")
				ui.Render(ui.Body)
			}
		}
	}
	go uiRoutine()

	Info.Println("Sending initial draw signal")

	//handle container addition/removal
	Info.Println("Spinning off container change routine")
	containerChangeRoutine := func() {
		currentContainers := make(map[string]*goDocker.Container)
		for {
			select {
			case newContainerID := <-startedContainerChan:
				Info.Println("Got new container event")
				cont, err := docker.InspectContainer(newContainerID)
				if err != nil {
					Error.Println("Failed to inspect new container", newContainerID, ":", err)
					continue
				}
				currentContainers[cont.ID] = cont
				maxOffsetChan <- len(currentContainers) - 1
				containersChan <- currentContainers
				startGatheringStatisticsChan <- cont.ID

			case removedContainerID := <-deadContainerChan:
				Info.Println("Got dead container event")
				delete(currentContainers, removedContainerID)
				maxOffsetChan <- len(currentContainers) - 1
				containersChan <- currentContainers
				stopGatheringStatisticsChan <- removedContainerID
			}
		}
	}
	go containerChangeRoutine()

	Info.Println("Spinning off update widgets routine")
	updateWidgets := func() {
		lastContainersList := make(map[string]*goDocker.Container)
		offset := 0
		horizPosition := 0
		for {
			select {
			case hp := <-horizPositionChan:
				horizPosition = hp
				Info.Println("Got changed horiz position", horizPosition)
				updateContainerList(containerListLeft, containerListRight, lastContainersList, offset, DockerInfoType(horizPosition))
				drawChan <- true
			case containers := <-containersChan:
				Info.Println("Got containers changed event")
				updateContainerList(containerListLeft, containerListRight, containers, offset, DockerInfoType(horizPosition))
				lastContainersList = containers
				drawChan <- true
			case offset = <-listStartOffsetChan:
				Info.Println("Got list offset of", offset)
				updateContainerList(containerListLeft, containerListRight, lastContainersList, offset, DockerInfoType(horizPosition))
				drawChan <- true
			}
		}
	}
	go updateWidgets()

	dockerEventRouting := func() {
		for {
			select {
			case e := <-dockerEventChan:
				switch e.Status {
				case "start":
					startedContainerChan <- e.ID
				case "die":
					deadContainerChan <- e.ID
				}
			}
		}
	}

	go dockerEventRouting()

	//setup initial containers
	containers, _ := docker.ListContainers(goDocker.ListContainersOptions{})
	drawChan <- true
	Info.Println("Listing intial", len(containers), "containers as started")
	for _, cont := range containers {
		startedContainerChan <- cont.ID
	}

	<-doneChan

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	. "github.com/0x19/goesl"
	"github.com/jmcvetta/restclient"
	. "github.com/xuyu/goredis"
	"runtime"
	"strings"
)

var (
	goeslMessage = "Hello from GoESL. Open source FreeSWITCH event socket wrapper written in Go!"
)

type ServerInfo struct {
	Company     int
	Tenant      int
	Class       string
	Type        string
	Category    string
	CallbackUrl string
	ServerID    int
}

type RequestData struct {
	Company         int
	Tenant          int
	Class           string
	Type            string
	Category        string
	SessionId       string
	Attributes      []string
	Priority        string
	RequestServerId string
	OtherInfo       string
}

type Request1 struct {
	Request1 RequestData
}

/*

public class InputData
    {
        public int Company { get; set; }
        public int Tenant { get; set; }
        public string Class { get; set; }
        public string Type { get; set; }
        public string Category { get; set; }
        public string SessionId { get; set; }
        public List<string> Attributes { get; set; }
        public string RequestServerId { get; set; }
        public string Priority { get; set; }
        public string OtherInfo { get; set; }
    }

*/

var client *Redis

func main() {

	defer func() {
		if r := recover(); r != nil {
			Error("Recovered in: ", r)
		}
	}()

	// Boost it as much as it can go ...
	runtime.GOMAXPROCS(runtime.NumCPU())

	///////////////////////register with ards as a requester//////////////////////////////////////////

	registered := true

	f := ServerInfo{
		Company:     1,
		Tenant:      3,
		Class:       "CALLSERVER",
		Type:        "ARDS",
		Category:    "CALL",
		CallbackUrl: "http://192.168.0.79:8086/route",
		ServerID:    1,
	}

	r := restclient.RequestResponse{
		Url:    "http://192.168.0.25:2225/requestserver/add",
		Method: "POST",
		Data:   &f,
		Result: &registered,
	}
	status, err := restclient.Do(&r)
	if err != nil {
		//panic(err)
	}
	if status == 200 {
		println(registered)
	}

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

	if s, err := NewOutboundServer(":8084"); err != nil {
		Error("Got error while starting FreeSWITCH outbound server: %s", err)
	} else {
		go handle(s)
		s.Start()
	}

}

// handle - Running under goroutine here to explain how to run tts outbound server
func handle(s *OutboundServer) {

	client, err := Dial(&DialConfig{Address: "127.0.0.1:6379"})

	if err != nil {

		Error("Error occur in connecting redis", err)
		return

	}

	for {

		select {

		case conn := <-s.Conns:
			Notice("New incomming connection: %v", conn)

			if err := conn.Connect(); err != nil {
				Error("Got error while accepting connection: %s", err)

				break
			}

			msg, err := conn.ReadMessage()

			if err == nil && msg != nil {

				//conn.Send("myevents")
				Debug("Connect message %s", msg.Headers)

				uniqueID := msg.GetCallUUID()
				from := msg.GetHeader("Caller-Caller-Id-Number")
				to := msg.GetHeader("Caller-Destination-Number")
				direction := msg.GetHeader("Call-Direction")
				channelStatus := msg.GetHeader("Answer-State")
				originateSession := msg.GetHeader("Variable_originate_session_uuid")
				fsUUID := msg.GetHeader("Core-Uuid")
				fsHost := msg.GetHeader("Freeswitch-Hostname")
				fsName := msg.GetHeader("Freeswitch-Switchname")
				fsIP := msg.GetHeader("Freeswitch-Ipv4")
				callerContext := msg.GetHeader("Caller-Context")

				//conn.Send(fmt.Sprintf("myevent json %s", uniqueID))

				if len(originateSession) == 0 {

					Debug("New Session created --->  %s", uniqueID)

				} else {

				}

				Debug(from)
				Debug(to)
				Debug(direction)
				Debug(channelStatus)
				Debug(fsUUID)
				Debug(fsHost)
				Debug(fsName)
				Debug(fsIP)
				Debug(originateSession)
				Debug(callerContext)

				if direction == "outbound" {
					Debug("OutBound Call recived ---->")

					if channelStatus != "answered" {
						////////////////////////////////////////////////////////////
						if len(originateSession) > 0 {

							Debug("Original session found %s", originateSession)

							var isStored = true
							partykey := fmt.Sprintf("ARDS:Leg:%s", uniqueID)
							key := fmt.Sprintf("ARDS:Session:%s", originateSession)

							exsists, exsisterr := client.Exists(key)
							if exsisterr == nil && exsists == true {

								redisErr := client.SimpleSet(partykey, originateSession)
								Debug("Store Data : %s ", redisErr)
								isStored, redisErr = client.HSet(key, "AgentStatus", "AgentFound")
								Debug("Store Data : %s %s", isStored, redisErr)
								isStored, redisErr = client.HSet(key, "AgentUUID", uniqueID)
								Debug("Store Data : %s %s", isStored, redisErr)
								//msg, err = conn.Execute("wait_for_answer", "", true)
								//Debug("wait for answer ----> %s", msg)
								//msg, err = conn.ExecuteSet("CHANNEL_CONNECTION", "true", false)
								//Debug("Set variable ----> %s", msg)

								conn.Send("myevents json")

							} else {

								cmd := fmt.Sprintf("uuid_kill %s ", uniqueID)
								Debug(cmd)
								conn.BgApi(cmd)

							}

							go func() {
								for {
									msg, err := conn.ReadMessage()

									if err != nil {

										// If it contains EOF, we really dont care...
										if !strings.Contains(err.Error(), "EOF") {
											Error("Error while reading Freeswitch message: %s", err)
										}
										break
									} else {
										if msg != nil {

											uuid := msg.GetHeader("Unique-ID")
											Debug(uuid)

											contentType := msg.GetHeader("Content-Type")
											event := msg.GetHeader("Event-Name")
											if contentType == "text/disconnect-notice" {

												//key := fmt.Sprintf("ARDS:Session:%s", uniqueID)

											} else {

												if event == "CHANNEL_ANSWER" {

													client.HSet(key, "AgentStatus", "AgentConnected")

													cmd := fmt.Sprintf("uuid_bridge %s %s", originateSession, uniqueID)
													Debug(cmd)
													conn.BgApi(cmd)
													/////////////////////Remove///////////////////////

												} else if event == "CHANNEL_HANGUP" {

													value1, getErr1 := client.HGet(key, "AgentStatus")
													agentstatus := string(value1[:])
													if getErr1 == nil {

														if agentstatus != "AgentConnected" {

															//////////////////////////////Reject//////////////////////////////////////////////
														}
													}

												}
											}
										}
									}

									Debug("Got message: %s", msg)
								}
								Debug("Leaving go routing after everithing completed Inbound")
								client.Del(key)
								client.Del(partykey)
							}()

						}
						/////////////////////////////////////////////////////////////
					}

				} else {

					answer, err := conn.ExecuteAnswer("", false)

					if err != nil {
						Error("Got error while executing answer: %s", err)
						break
					}

					Debug("Answer Message: %s", answer)
					Debug("Caller UUID: %s", uniqueID)

					//////////////////////////////////////////Add to queue//////////////////////////////////////
					var registered string

					attrib := []string{"123456"}
					f := RequestData{
						Company:         1,
						Tenant:          3,
						Class:           "CALLSERVER",
						Type:            "ARDS",
						Category:        "CALL",
						SessionId:       uniqueID,
						RequestServerId: "1",
						Priority:        "L",
						OtherInfo:       "",
						Attributes:      attrib,
					}

					postData := Request1{

						Request1: f,
					}

					r := restclient.RequestResponse{
						Url:    "http://192.168.0.25:2221/startArds/web/Start",
						Method: "POST",
						Data:   &postData,
						Result: &registered,
					}
					status, err := restclient.Do(&r)
					if err != nil {
						//panic(err)
						fmt.Printf("%s", err)
					}
					if status == 200 {
						fmt.Printf(registered)
					}

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

					key := fmt.Sprintf("ARDS:Session:%s", uniqueID)

					partykey := fmt.Sprintf("ARDS:Leg:%s", uniqueID)
					var isStored = true
					Debug("key ---> %s ", partykey)
					redisErr := client.SimpleSet(partykey, uniqueID)
					Debug("Store Data : %s ", redisErr)

					Debug("key ---> %s ", key)
					isStored, redisErr = client.HSet(key, "CallStatus", "CallOnQueue")
					Debug("Store Data : %s ", redisErr)
					isStored, redisErr = client.HSet(key, "AgentStatus", "NotFound")

					Debug("Store Data : %s %s ", redisErr, isStored)

					conn.Send("myevents json")
					if sm, err := conn.Execute("playback", "local_stream://moh", false); err != nil {
						Error("Got error while executing speak: %s", err)
						break
					} else {

						Debug("Playback reply %s", sm)

					}

					Debug("Leaving go routing after everithing completed Inbound")

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

					go func() {

						for {
							msg, err := conn.ReadMessage()

							if err != nil {

								// If it contains EOF, we really dont care...
								if !strings.Contains(err.Error(), "EOF") {
									Error("Error while reading Freeswitch message: %s", err)
								}

								break
							} else {
								if msg != nil {

									uuid := msg.GetHeader("Unique-ID")
									Debug(uuid)

									contentType := msg.GetHeader("Content-Type")
									event := msg.GetHeader("Event-Name")
									application := msg.GetHeader("variable_current_application")
									//response := msg.GetHeader("variable_current_application_response")
									if contentType == "text/disconnect-notice" {

										//key := fmt.Sprintf("ARDS:Session:%s", uniqueID)

									} else {

										if event == "CHANNEL_EXECUTE_COMPLETE" && application == "playback" {

											value1, getErr1 := client.HGet(key, "AgentStatus")
											sValue1 := string(value1[:])

											value2, getErr2 := client.HGet(key, "AgentUUID")
											sValue2 := string(value2[:])

											Debug("Client side connection values %s %s %s %s", getErr1, getErr2, sValue1, sValue2)

											if getErr1 == nil && getErr2 == nil && sValue1 == "AgentConnected" && len(sValue2) > 0 {

											}
										} else if event == "CHANNEL_HANGUP" {

											value1, getErr1 := client.HGet(key, "AgentStatus")
											agentstatus := string(value1[:])
											if getErr1 == nil {

												if agentstatus != "AgentConnected" {

													//////////////////////////////Remove//////////////////////////////////////////////
												}
											}

										}
									}
								}
							}
							//Debug("Got message: %s", msg)
						}
						Debug("Leaving go routing after everithing completed Inbound")
						client.Del(key)
						client.Del(partykey)
					}()

				}

			} else {

				Error("Got Error %s", err)
				conn.Exit()
			}

		default:
		}
	}

}
<commit_msg>ADD reject and remove rest commands<commit_after>package main

import (
	"fmt"
	. "github.com/0x19/goesl"
	"github.com/jmcvetta/restclient"
	. "github.com/xuyu/goredis"
	"runtime"
	"strings"
)

var (
	goeslMessage = "Hello from GoESL. Open source FreeSWITCH event socket wrapper written in Go!"
)

type ServerInfo struct {
	Company     int
	Tenant      int
	Class       string
	Type        string
	Category    string
	CallbackUrl string
	ServerID    int
}

type RequestData struct {
	Company         int
	Tenant          int
	Class           string
	Type            string
	Category        string
	SessionId       string
	Attributes      []string
	Priority        string
	RequestServerId string
	OtherInfo       string
}

type Request1 struct {
	Request1 RequestData
}

/*

public class InputData
    {
        public int Company { get; set; }
        public int Tenant { get; set; }
        public string Class { get; set; }
        public string Type { get; set; }
        public string Category { get; set; }
        public string SessionId { get; set; }
        public List<string> Attributes { get; set; }
        public string RequestServerId { get; set; }
        public string Priority { get; set; }
        public string OtherInfo { get; set; }
    }

*/

var client *Redis

func main() {

	defer func() {
		if r := recover(); r != nil {
			Error("Recovered in: ", r)
		}
	}()

	// Boost it as much as it can go ...
	runtime.GOMAXPROCS(runtime.NumCPU())

	///////////////////////register with ards as a requester//////////////////////////////////////////

	registered := true

	f := ServerInfo{
		Company:     1,
		Tenant:      3,
		Class:       "CALLSERVER",
		Type:        "ARDS",
		Category:    "CALL",
		CallbackUrl: "http://192.168.0.79:8086/route",
		ServerID:    1,
	}

	r := restclient.RequestResponse{
		Url:    "http://192.168.0.25:2225/requestserver/add",
		Method: "POST",
		Data:   &f,
		Result: &registered,
	}
	status, err := restclient.Do(&r)
	if err != nil {
		//panic(err)
	}
	if status == 200 {
		println(registered)
	}

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

	if s, err := NewOutboundServer(":8084"); err != nil {
		Error("Got error while starting FreeSWITCH outbound server: %s", err)
	} else {
		go handle(s)
		s.Start()
	}

}

func RemoveRequest(company, tenant, sessionid string) {

	r := restclient.RequestResponse{
		Url:    fmt.Sprintf("http://192.168.0.25:2225/request/remove/%s/%s/%s", company, tenant, sessionid),
		Method: "DELETE",
	}
	status, err := restclient.Do(&r)
	if err != nil {
		//panic(err)
		fmt.Printf("MSG error -------------------------------------> %s", err)
	}
	if status == 200 {
		//fmt.Printf(registered)
	}

}

func RejectRequest(company, tenant, sessionid, reason string) {

	r := restclient.RequestResponse{
		Url:    fmt.Sprintf("http://192.168.0.25:2225/request/reject/%s/%s/%s/%s", company, tenant, sessionid, reason),
		Method: "DELETE",
	}
	status, err := restclient.Do(&r)
	if err != nil {
		//panic(err)
		fmt.Printf("MSG error -------------------------------------> %s", err)
	}
	if status == 200 {
		//fmt.Printf(registered)
	}

}

// handle - Running under goroutine here to explain how to run tts outbound server
func handle(s *OutboundServer) {

	client, err := Dial(&DialConfig{Address: "127.0.0.1:6379"})

	if err != nil {

		Error("Error occur in connecting redis", err)
		return

	}

	for {

		select {

		case conn := <-s.Conns:
			Notice("New incomming connection: %v", conn)

			if err := conn.Connect(); err != nil {
				Error("Got error while accepting connection: %s", err)

				break
			}

			msg, err := conn.ReadMessage()

			if err == nil && msg != nil {

				//conn.Send("myevents")
				Debug("Connect message %s", msg.Headers)

				uniqueID := msg.GetCallUUID()
				from := msg.GetHeader("Caller-Caller-Id-Number")
				to := msg.GetHeader("Caller-Destination-Number")
				direction := msg.GetHeader("Call-Direction")
				channelStatus := msg.GetHeader("Answer-State")
				originateSession := msg.GetHeader("Variable_originate_session_uuid")
				fsUUID := msg.GetHeader("Core-Uuid")
				fsHost := msg.GetHeader("Freeswitch-Hostname")
				fsName := msg.GetHeader("Freeswitch-Switchname")
				fsIP := msg.GetHeader("Freeswitch-Ipv4")
				callerContext := msg.GetHeader("Caller-Context")

				//conn.Send(fmt.Sprintf("myevent json %s", uniqueID))

				if len(originateSession) == 0 {

					Debug("New Session created --->  %s", uniqueID)

				} else {

				}

				Debug(from)
				Debug(to)
				Debug(direction)
				Debug(channelStatus)
				Debug(fsUUID)
				Debug(fsHost)
				Debug(fsName)
				Debug(fsIP)
				Debug(originateSession)
				Debug(callerContext)

				if direction == "outbound" {
					Debug("OutBound Call recived ---->")

					if channelStatus != "answered" {
						////////////////////////////////////////////////////////////
						if len(originateSession) > 0 {

							Debug("Original session found %s", originateSession)

							var isStored = true
							partykey := fmt.Sprintf("ARDS:Leg:%s", uniqueID)
							key := fmt.Sprintf("ARDS:Session:%s", originateSession)

							exsists, exsisterr := client.Exists(key)
							if exsisterr == nil && exsists == true {

								redisErr := client.SimpleSet(partykey, originateSession)
								Debug("Store Data : %s ", redisErr)
								isStored, redisErr = client.HSet(key, "AgentStatus", "AgentFound")
								Debug("Store Data : %s %s", isStored, redisErr)
								isStored, redisErr = client.HSet(key, "AgentUUID", uniqueID)
								Debug("Store Data : %s %s", isStored, redisErr)
								//msg, err = conn.Execute("wait_for_answer", "", true)
								//Debug("wait for answer ----> %s", msg)
								//msg, err = conn.ExecuteSet("CHANNEL_CONNECTION", "true", false)
								//Debug("Set variable ----> %s", msg)

							} else {

								RejectRequest("1", "3", originateSession, "ClientReject")

								cmd := fmt.Sprintf("uuid_kill %s ", uniqueID)
								Debug(cmd)
								conn.BgApi(cmd)

							}

							conn.Send("myevents json")
							go func() {
								for {
									msg, err := conn.ReadMessage()

									if err != nil {

										// If it contains EOF, we really dont care...
										if !strings.Contains(err.Error(), "EOF") {
											Error("Error while reading Freeswitch message: %s", err)

										}
										break

									} else {
										if msg != nil {

											uuid := msg.GetHeader("Unique-ID")
											Debug(uuid)

											contentType := msg.GetHeader("Content-Type")
											event := msg.GetHeader("Event-Name")
											Debug("Content types -------------------->", contentType)

											if contentType == "text/disconnect-notice" {

												//key := fmt.Sprintf("ARDS:Session:%s", uniqueID)

											} else {

												if event == "CHANNEL_ANSWER" {

													client.HSet(key, "AgentStatus", "AgentConnected")

													cmd := fmt.Sprintf("uuid_bridge %s %s", originateSession, uniqueID)
													Debug(cmd)
													conn.BgApi(cmd)
													/////////////////////Remove///////////////////////

													RemoveRequest("1", "3", originateSession)

												} else if event == "CHANNEL_HANGUP" {

													value1, getErr1 := client.HGet(key, "AgentStatus")
													agentstatus := string(value1[:])
													if getErr1 == nil {

														if agentstatus != "AgentConnected" {

															//////////////////////////////Reject//////////////////////////////////////////////
															//http://localhost:2225/request/remove/company/tenant/sessionid

															RejectRequest("1", "3", originateSession, "AgentRejected")

														}
													}

												}
											}
										}
									}

									Debug("Got message: %s", msg)
								}
								Debug("Leaving go routing after everithing completed OutBound %s %s", key, partykey)
								//client.Del(key)
								client.Del(partykey)
							}()

						}
						/////////////////////////////////////////////////////////////
					}

				} else {

					answer, err := conn.ExecuteAnswer("", false)

					if err != nil {
						Error("Got error while executing answer: %s", err)

					}

					Debug("Answer Message: %s", answer)
					Debug("Caller UUID: %s", uniqueID)

					//////////////////////////////////////////Add to queue//////////////////////////////////////
					var registered string

					attrib := []string{"123456"}
					f := RequestData{
						Company:         1,
						Tenant:          3,
						Class:           "CALLSERVER",
						Type:            "ARDS",
						Category:        "CALL",
						SessionId:       uniqueID,
						RequestServerId: "1",
						Priority:        "L",
						OtherInfo:       "",
						Attributes:      attrib,
					}

					postData := Request1{

						Request1: f,
					}

					r := restclient.RequestResponse{
						Url:    "http://192.168.0.25:2221/startArds/web/Start",
						Method: "POST",
						Data:   &postData,
						Result: &registered,
					}
					status, err := restclient.Do(&r)
					if err != nil {
						//panic(err)
						fmt.Printf("%s", err)
					}
					if status == 200 {
						fmt.Printf(registered)
					}

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

					key := fmt.Sprintf("ARDS:Session:%s", uniqueID)

					partykey := fmt.Sprintf("ARDS:Leg:%s", uniqueID)
					var isStored = true
					Debug("key ---> %s ", partykey)
					redisErr := client.SimpleSet(partykey, uniqueID)
					Debug("Store Data : %s ", redisErr)

					Debug("key ---> %s ", key)
					isStored, redisErr = client.HSet(key, "CallStatus", "CallOnQueue")
					Debug("Store Data : %s ", redisErr)
					isStored, redisErr = client.HSet(key, "AgentStatus", "NotFound")

					Debug("Store Data : %s %s ", redisErr, isStored)

					conn.Send("myevents json")
					if sm, err := conn.Execute("playback", "local_stream://moh", false); err != nil {
						Error("Got error while executing speak: %s", err)

					} else {

						Debug("Playback reply %s", sm)

					}

					Debug("Leaving go routing after everithing completed Inbound")

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

					go func() {

						for {
							msg, err := conn.ReadMessage()

							if err != nil {

								// If it contains EOF, we really dont care...
								if !strings.Contains(err.Error(), "EOF") {
									Error("Error while reading Freeswitch message: %s", err)

								}

								break

							} else {
								if msg != nil {

									uuid := msg.GetHeader("Unique-ID")
									Debug(uuid)

									contentType := msg.GetHeader("Content-Type")
									event := msg.GetHeader("Event-Name")
									application := msg.GetHeader("variable_current_application")

									Debug("Content types -------------------->", contentType)
									//response := msg.GetHeader("variable_current_application_response")
									if contentType == "text/disconnect-notice" {

										//key := fmt.Sprintf("ARDS:Session:%s", uniqueID)

									} else {

										if event == "CHANNEL_EXECUTE_COMPLETE" && application == "playback" {

											value1, getErr1 := client.HGet(key, "AgentStatus")
											sValue1 := string(value1[:])

											value2, getErr2 := client.HGet(key, "AgentUUID")
											sValue2 := string(value2[:])

											Debug("Client side connection values %s %s %s %s", getErr1, getErr2, sValue1, sValue2)

											if getErr1 == nil && getErr2 == nil && sValue1 == "AgentConnected" && len(sValue2) > 0 {

											}
										} else if event == "CHANNEL_HANGUP" {

											value1, getErr1 := client.HGet(key, "AgentStatus")
											agentstatus := string(value1[:])
											if getErr1 == nil {

												if agentstatus != "AgentConnected" {

													//////////////////////////////Remove//////////////////////////////////////////////

													RemoveRequest("1", "3", uniqueID)
												}
											}

										}
									}
								}
							}
							//Debug("Got message: %s", msg)
						}
						Debug("Leaving go routing after everithing completed Inbound %s %s", key, partykey)
						client.Del(key)
						client.Del(partykey)
					}()

				}

			} else {

				Error("Got Error %s", err)
				conn.Exit()
			}

		default:
		}
	}

}
<|endoftext|>


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

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/line/line-bot-sdk-go/linebot"
)

var ImgSrv string = "https://img-cache-server.herokuapp.com/"
var bot *linebot.Client

//PetDB :
var PetDB *Pets

func main() {
	var err error
	PetDB = NewPets()
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func getSecureImageAddress(oriAdd string) string {
	eURL := url.QueryEscape(oriAdd)
	imgGetUrl := fmt.Sprintf("%surl?%s", ImgSrv, eURL)
	log.Println("eURL:", eURL, " url:", imgGetUrl, " ImgApi:", ImgSrv)

	response, err := http.Get(imgGetUrl)
	if err != nil {
		log.Println("Error while downloading:", err)
		return ""
	}
	defer response.Body.Close()

	if response.StatusCode != 200 {
		return ""
	}

	totalBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Println("Error while parsing:", err)
		return ""
	}
	log.Println("Got data:", string(totalBody))
	return fmt.Sprintf("%simgs?%s.jpg", ImgSrv, string(totalBody))

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, event := range events {
		switch event.Type {
		case linebot.EventTypeMessage:
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				var pet *Pet
				log.Println(message.Text)
				inText := strings.ToLower(message.Text)
				if strings.Contains(inText, "狗") || strings.Contains(inText, "dog") {
					pet = PetDB.GetNextDog()
				} else if strings.Contains(inText, "貓") || strings.Contains(inText, "cat") {
					pet = PetDB.GetNextCat()
				} else if strings.Contains(inText, "link") {
					var userID string
					if event.Source != nil {
						userID = event.Source.UserID
					}

					if err := bot.IssueLinkToken(userID).Do; err != nil {
						fmt.Println("Issue link error:", err)
					}
				}

				if pet == nil {
					pet = PetDB.GetNextPet()
				}

				out := fmt.Sprintf("您好，目前的動物名為%s, 所在地為:%s, 電話為:%s ", pet.Name, pet.Resettlement, pet.Phone)
				log.Println("Current msg:", out)
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(out)).Do(); err != nil {
					log.Print(err)
				}

			}
		case linebot.EventTypeBeacon:
			log.Println(" Beacon event....")
			if b := event.Beacon; b != nil {
				ret := fmt.Sprintln("Msg:", string(b.DeviceMessage), " hwid:", b.Hwid, " type:", b.Type)
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(ret)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}
<commit_msg>display user ID<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/line/line-bot-sdk-go/linebot"
)

var ImgSrv string = "https://img-cache-server.herokuapp.com/"
var bot *linebot.Client

//PetDB :
var PetDB *Pets

func main() {
	var err error
	PetDB = NewPets()
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func getSecureImageAddress(oriAdd string) string {
	eURL := url.QueryEscape(oriAdd)
	imgGetUrl := fmt.Sprintf("%surl?%s", ImgSrv, eURL)
	log.Println("eURL:", eURL, " url:", imgGetUrl, " ImgApi:", ImgSrv)

	response, err := http.Get(imgGetUrl)
	if err != nil {
		log.Println("Error while downloading:", err)
		return ""
	}
	defer response.Body.Close()

	if response.StatusCode != 200 {
		return ""
	}

	totalBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Println("Error while parsing:", err)
		return ""
	}
	log.Println("Got data:", string(totalBody))
	return fmt.Sprintf("%simgs?%s.jpg", ImgSrv, string(totalBody))

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, event := range events {
		switch event.Type {
		case linebot.EventTypeMessage:
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				var pet *Pet
				log.Println(message.Text)
				inText := strings.ToLower(message.Text)
				if strings.Contains(inText, "狗") || strings.Contains(inText, "dog") {
					pet = PetDB.GetNextDog()
				} else if strings.Contains(inText, "貓") || strings.Contains(inText, "cat") {
					pet = PetDB.GetNextCat()
				} else if strings.Contains(inText, "link") {
					var userID string
					if event.Source != nil {
						userID = event.Source.UserID
					}

					if err := bot.IssueLinkToken(userID).Do; err != nil {
						fmt.Println("Issue link error:", err, " userID is:", userID)
					}
				}

				if pet == nil {
					pet = PetDB.GetNextPet()
				}

				out := fmt.Sprintf("您好，目前的動物名為%s, 所在地為:%s, 電話為:%s ", pet.Name, pet.Resettlement, pet.Phone)
				log.Println("Current msg:", out)
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(out)).Do(); err != nil {
					log.Print(err)
				}

			}
		case linebot.EventTypeBeacon:
			log.Println(" Beacon event....")
			if b := event.Beacon; b != nil {
				ret := fmt.Sprintln("Msg:", string(b.DeviceMessage), " hwid:", b.Hwid, " type:", b.Type)
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(ret)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}
<|endoftext|>