<commit_before>package main

import (
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/kusubooru/local-tagger/bulk"
)

//go:generate go run generate/templates.go
//go:generate go run generate/swf.go

const theVersion = "1.0.0"

var fns = template.FuncMap{
	"last": func(s []string) string {
		if len(s) == 0 {
			return ""
		}
		return s[len(s)-1]
	},
	"join": strings.Join,
}

var (
	directory   = flag.String("dir", ".", "the directory that contains the images")
	csvFilename = flag.String("csv", "bulk.csv", "the name of the CSV file")
	port        = flag.String("port", "8080", "server port")
	openBrowser = flag.Bool("openbrowser", true, "open browser automatically")
	version     = flag.Bool("v", false, "print program version")
)

const description = `Usage: local-tagger [options]

  User interface for the 'Bulk Add CSV' extension of Shimmie2.

  local-tagger will launch a web interface in a new browser window, which
  allows to add tags, source and rating on each image that is contained in the
  current directory (or the one specified by the -dir option). Subfolders are
  ignored. Supported types: "gif", "jpeg", "jpg", "png", "swf"

  The web interface allows to save the image metadata in a CSV file as expected
  by the 'Bulk Add CSV' Shimmie2 extension. If a CSV file with the name
  'bulk.csv' (or a name specified by the -csv option) is found, it will be
  loaded automatically on start up.

  The folder containing the CSV file and the images can then be manually
  uploaded to the server and used by the 'Bulk Add CSV' extension to bulk add
  the images to Shimmie2.

Options:

`

func usage() {
	fmt.Fprintf(os.Stderr, description)
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\n")
}

type model struct {
	Err         error
	Prefix      string
	Dir         string
	CSVFilename string
	Images      []bulk.Image
	Version     string
	UseLinuxSep bool
}

var globalModel *model

func main() {
	if err := run(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

func createFile(file string) error {
	f, err := os.Create(file)
	if err != nil {
		return err
	}
	defer func() {
		if cerr := f.Close(); cerr != nil {
			err = cerr
		}
	}()
	return err
}

func run() error {
	flag.Usage = usage
	flag.Parse()

	if *version {
		fmt.Printf("local-tagger%v\n", theVersion)
		return nil
	}

	d, err := filepath.Abs(*directory)
	if err != nil {
		return err
	}
	*directory = d

	// If CSV File does not exist, we create it.
	csvFile := filepath.Join(*directory, *csvFilename)
	if _, err = os.Stat(csvFile); os.IsNotExist(err) {
		if err = createFile(csvFile); err != nil {
			return err
		}
	}

	m, err := loadFromCSVFile(*directory, *csvFilename)
	if err != nil {
		return err
	}
	globalModel = m

	http.Handle("/", http.HandlerFunc(indexHandler))
	http.Handle("/load", http.HandlerFunc(loadHandler))
	http.Handle("/update", http.HandlerFunc(updateHandler))
	http.Handle("/ok/", http.HandlerFunc(okHandler))
	http.Handle("/img/", http.HandlerFunc(serveImage))
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static"))))

	go func() {
		localURL := fmt.Sprintf("http://localhost:%v", *port)
		okURL := fmt.Sprintf("%v/ok", localURL)
		if waitServer(okURL) && *openBrowser && startBrowser(localURL) {
			log.Printf("A browser window should open. If not, please visit %s", localURL)
		} else {
			log.Printf("Please open your web browser and visit %s", localURL)
		}
	}()

	if err := http.ListenAndServe(":"+*port, nil); err != nil {
		return err
	}

	return nil
}

func loadFromCSVFile(dir, csvFilename string) (*model, error) {

	m := &model{Dir: dir, CSVFilename: csvFilename, Version: theVersion}
	if globalModel != nil {
		m.UseLinuxSep = globalModel.UseLinuxSep
	}

	// Loading images from folder
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	images := bulk.LoadImages(files)

	f, err := os.Open(filepath.Join(dir, csvFilename))
	if err != nil {
		return nil, err
	}
	defer func() {
		if cerr := f.Close(); cerr != nil && err == nil {
			err = cerr
		}
	}()

	// Loading CSV image data
	imagesWithInfo, err := bulk.LoadCSV(f)
	if err != nil {
		return nil, err
	}
	m.Images = bulk.Combine(images, imagesWithInfo)

	// Getting current prefix
	if _, err = f.Seek(0, 0); err != nil {
		return nil, err
	}
	cp, err := bulk.CurrentPrefix(dir, f)
	if err != nil {
		return nil, err
	}
	m.Prefix = cp

	return m, nil
}

func loadHandler(w http.ResponseWriter, r *http.Request) {
	f, h, err := r.FormFile("csvFilename")
	if err != nil {
		globalModel.Err = fmt.Errorf("Error: could not parse multipart file: %v", err)
		render(w, indexTmpl, globalModel)
		return
	}
	defer func() {
		if cerr := f.Close(); cerr != nil {
			log.Printf("Error: could not close multipart file: %v\n", cerr)
		}
	}()

	if err := addFromMultipartFile(globalModel, f); err != nil {
		globalModel.Err = fmt.Errorf("Error: could not load image metadata from multipart CSV File: %v", err)
		render(w, indexTmpl, globalModel)
		return
	}
	globalModel.CSVFilename = h.Filename

	err = saveToCSVFile(globalModel)
	if err != nil {
		globalModel.Err = fmt.Errorf("Error: could not save file to disk: %v", err)
		render(w, indexTmpl, globalModel)
		return
	}
	http.Redirect(w, r, "/", http.StatusFound)
}
func addFromMultipartFile(m *model, file multipart.File) error {
	imgMetadata, err := bulk.LoadCSV(file)
	if err != nil {
		return fmt.Errorf("could not load image info from CSV File: %v", err)
	}
	if _, err = file.Seek(0, 0); err != nil {
		return fmt.Errorf("could not seek multipart file: %v", err)
	}
	prefix, err := bulk.CurrentPrefix(m.Dir, file)
	if err != nil {
		return fmt.Errorf("could not read current prefix from multipart file: %v", err)
	}
	m.Prefix = prefix
	m.Images = bulk.Combine(m.Images, imgMetadata)

	return nil
}

func okHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("ok"))
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	m, err := loadFromCSVFile(globalModel.Dir, globalModel.CSVFilename)
	if err != nil {
		globalModel.Err = fmt.Errorf("Error: could not load from CSV File: %v", err)
	} else {
		globalModel = m
	}

	render(w, indexTmpl, globalModel)
}

func render(w http.ResponseWriter, t *template.Template, model interface{}) {
	if err := t.Execute(w, model); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func updateHandler(w http.ResponseWriter, r *http.Request) {

	if err := r.ParseForm(); err != nil {
		http.Error(w, "could not parse form", http.StatusInternalServerError)
		return
	}

	// prefix
	globalModel.Prefix = r.PostForm["prefix"][0]
	// csvFilename
	globalModel.CSVFilename = r.PostForm["csvFilename"][0]
	for _, img := range globalModel.Images {
		// tags
		areaTags := r.PostForm[fmt.Sprintf("image[%d].tags", img.ID)]
		globalModel.Images[img.ID].Tags = strings.Fields(areaTags[0])
		// source
		globalModel.Images[img.ID].Source = r.PostForm[fmt.Sprintf("image[%d].source", img.ID)][0]
		// rating
		rating := r.PostForm[fmt.Sprintf("image[%d].rating", img.ID)]
		if len(rating) != 0 {
			globalModel.Images[img.ID].Rating = rating[0]
		}
	}
	// UseLinuxSep
	_, ok := r.PostForm["useLinuxSep"]
	if ok {
		globalModel.UseLinuxSep = true
	} else {
		globalModel.UseLinuxSep = false
	}
	// scroll
	scroll := r.PostForm["scroll"][0]

	if err := saveToCSVFile(globalModel); err != nil {
		globalModel.Err = fmt.Errorf("Error: could not save to CSV file: %v", err)
		render(w, indexTmpl, globalModel)
	} else {
		globalModel.Err = nil
		http.Redirect(w, r, "/"+scroll, http.StatusFound)
	}
}

func saveToCSVFile(m *model) error {
	csvFilepath := filepath.Join(m.Dir, m.CSVFilename)
	f, err := os.Create(csvFilepath)
	if err != nil {
		return err
	}
	defer func() {
		if cerr := f.Close(); err != nil {
			err = cerr
		}
	}()

	if err := bulk.Save(f, m.Images, m.Dir, m.Prefix, m.UseLinuxSep); err != nil {
		return err
	}
	return err
}

func serveImage(w http.ResponseWriter, r *http.Request) {
	idStr := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:]
	id, err := strconv.Atoi(idStr)
	if err != nil {
		http.Error(w, fmt.Sprintf("%v is not a valid image ID", idStr), http.StatusBadRequest)
		return
	}
	img := bulk.FindByID(globalModel.Images, id)
	if img == nil {
		http.Error(w, fmt.Sprintf("no image found with ID: %v", id), http.StatusNotFound)
		return
	}
	// In case of image name that ends with '.swf', we serve embedded image
	// bytes from swf.go as it's not trivial to display a .swf file.
	if strings.HasSuffix(img.Name, ".swf") {
		_, err = w.Write(swfImageBytes)
		if err != nil {
			http.Error(w, fmt.Sprintf("could not write image bytes: %v", err), http.StatusInternalServerError)
			return
		}
	}

	p := filepath.Join(*directory, img.Name)
	f, err := os.Open(p)
	if err != nil {
		http.Error(w, fmt.Sprintf("could not open image: %v", err), http.StatusInternalServerError)
		return
	}
	defer func() {
		if cerr := f.Close(); cerr != nil {
			log.Printf("Error: could not close image file: %v\n", cerr)
		}
	}()
	data, err := ioutil.ReadAll(f)
	if err != nil {
		http.Error(w, fmt.Sprintf("could not read image: %v", err), http.StatusInternalServerError)
		return
	}
	_, err = w.Write(data)
	if err != nil {
		http.Error(w, fmt.Sprintf("could not write image bytes: %v", err), http.StatusInternalServerError)
		return
	}
}

// startBrowser tries to open the URL in a browser, and returns
// whether it succeed.
func startBrowser(url string) bool {
	// try to start the browser
	var args []string
	switch runtime.GOOS {
	case "darwin":
		args = []string{"open"}
	case "windows":
		args = []string{"cmd", "/c", "start"}
	default:
		args = []string{"xdg-open"}
	}
	cmd := exec.Command(args[0], append(args[1:], url)...)
	return cmd.Start() == nil
}

// waitServer waits some time for the http Server to start
// serving url. The return value reports whether it starts.
func waitServer(url string) bool {
	tries := 20
	for tries > 0 {
		resp, err := http.Get(url)
		if err == nil {
			resp.Body.Close()
			return true
		}
		time.Sleep(100 * time.Millisecond)
		tries--
	}
	return false
}
<commit_msg>Add main.go doc<commit_after>// User interface for the 'Bulk Add CSV' extension of Shimmie2.
package main

import (
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/kusubooru/local-tagger/bulk"
)

//go:generate go run generate/templates.go
//go:generate go run generate/swf.go

const theVersion = "1.0.0"

var fns = template.FuncMap{
	"last": func(s []string) string {
		if len(s) == 0 {
			return ""
		}
		return s[len(s)-1]
	},
	"join": strings.Join,
}

var (
	directory   = flag.String("dir", ".", "the directory that contains the images")
	csvFilename = flag.String("csv", "bulk.csv", "the name of the CSV file")
	port        = flag.String("port", "8080", "server port")
	openBrowser = flag.Bool("openbrowser", true, "open browser automatically")
	version     = flag.Bool("v", false, "print program version")
)

const description = `Usage: local-tagger [options]

  User interface for the 'Bulk Add CSV' extension of Shimmie2.

  local-tagger will launch a web interface in a new browser window, which
  allows to add tags, source and rating on each image that is contained in the
  current directory (or the one specified by the -dir option). Subfolders are
  ignored. Supported types: "gif", "jpeg", "jpg", "png", "swf"

  The web interface allows to save the image metadata in a CSV file as expected
  by the 'Bulk Add CSV' Shimmie2 extension. If a CSV file with the name
  'bulk.csv' (or a name specified by the -csv option) is found, it will be
  loaded automatically on start up.

  The folder containing the CSV file and the images can then be manually
  uploaded to the server and used by the 'Bulk Add CSV' extension to bulk add
  the images to Shimmie2.

Options:

`

func usage() {
	fmt.Fprintf(os.Stderr, description)
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\n")
}

type model struct {
	Err         error
	Prefix      string
	Dir         string
	CSVFilename string
	Images      []bulk.Image
	Version     string
	UseLinuxSep bool
}

var globalModel *model

func main() {
	if err := run(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

func createFile(file string) error {
	f, err := os.Create(file)
	if err != nil {
		return err
	}
	defer func() {
		if cerr := f.Close(); cerr != nil {
			err = cerr
		}
	}()
	return err
}

func run() error {
	flag.Usage = usage
	flag.Parse()

	if *version {
		fmt.Printf("local-tagger%v\n", theVersion)
		return nil
	}

	d, err := filepath.Abs(*directory)
	if err != nil {
		return err
	}
	*directory = d

	// If CSV File does not exist, we create it.
	csvFile := filepath.Join(*directory, *csvFilename)
	if _, err = os.Stat(csvFile); os.IsNotExist(err) {
		if err = createFile(csvFile); err != nil {
			return err
		}
	}

	m, err := loadFromCSVFile(*directory, *csvFilename)
	if err != nil {
		return err
	}
	globalModel = m

	http.Handle("/", http.HandlerFunc(indexHandler))
	http.Handle("/load", http.HandlerFunc(loadHandler))
	http.Handle("/update", http.HandlerFunc(updateHandler))
	http.Handle("/ok/", http.HandlerFunc(okHandler))
	http.Handle("/img/", http.HandlerFunc(serveImage))
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static"))))

	go func() {
		localURL := fmt.Sprintf("http://localhost:%v", *port)
		okURL := fmt.Sprintf("%v/ok", localURL)
		if waitServer(okURL) && *openBrowser && startBrowser(localURL) {
			log.Printf("A browser window should open. If not, please visit %s", localURL)
		} else {
			log.Printf("Please open your web browser and visit %s", localURL)
		}
	}()

	if err := http.ListenAndServe(":"+*port, nil); err != nil {
		return err
	}

	return nil
}

func loadFromCSVFile(dir, csvFilename string) (*model, error) {

	m := &model{Dir: dir, CSVFilename: csvFilename, Version: theVersion}
	if globalModel != nil {
		m.UseLinuxSep = globalModel.UseLinuxSep
	}

	// Loading images from folder
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	images := bulk.LoadImages(files)

	f, err := os.Open(filepath.Join(dir, csvFilename))
	if err != nil {
		return nil, err
	}
	defer func() {
		if cerr := f.Close(); cerr != nil && err == nil {
			err = cerr
		}
	}()

	// Loading CSV image data
	imagesWithInfo, err := bulk.LoadCSV(f)
	if err != nil {
		return nil, err
	}
	m.Images = bulk.Combine(images, imagesWithInfo)

	// Getting current prefix
	if _, err = f.Seek(0, 0); err != nil {
		return nil, err
	}
	cp, err := bulk.CurrentPrefix(dir, f)
	if err != nil {
		return nil, err
	}
	m.Prefix = cp

	return m, nil
}

func loadHandler(w http.ResponseWriter, r *http.Request) {
	f, h, err := r.FormFile("csvFilename")
	if err != nil {
		globalModel.Err = fmt.Errorf("Error: could not parse multipart file: %v", err)
		render(w, indexTmpl, globalModel)
		return
	}
	defer func() {
		if cerr := f.Close(); cerr != nil {
			log.Printf("Error: could not close multipart file: %v\n", cerr)
		}
	}()

	if err := addFromMultipartFile(globalModel, f); err != nil {
		globalModel.Err = fmt.Errorf("Error: could not load image metadata from multipart CSV File: %v", err)
		render(w, indexTmpl, globalModel)
		return
	}
	globalModel.CSVFilename = h.Filename

	err = saveToCSVFile(globalModel)
	if err != nil {
		globalModel.Err = fmt.Errorf("Error: could not save file to disk: %v", err)
		render(w, indexTmpl, globalModel)
		return
	}
	http.Redirect(w, r, "/", http.StatusFound)
}
func addFromMultipartFile(m *model, file multipart.File) error {
	imgMetadata, err := bulk.LoadCSV(file)
	if err != nil {
		return fmt.Errorf("could not load image info from CSV File: %v", err)
	}
	if _, err = file.Seek(0, 0); err != nil {
		return fmt.Errorf("could not seek multipart file: %v", err)
	}
	prefix, err := bulk.CurrentPrefix(m.Dir, file)
	if err != nil {
		return fmt.Errorf("could not read current prefix from multipart file: %v", err)
	}
	m.Prefix = prefix
	m.Images = bulk.Combine(m.Images, imgMetadata)

	return nil
}

func okHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("ok"))
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	m, err := loadFromCSVFile(globalModel.Dir, globalModel.CSVFilename)
	if err != nil {
		globalModel.Err = fmt.Errorf("Error: could not load from CSV File: %v", err)
	} else {
		globalModel = m
	}

	render(w, indexTmpl, globalModel)
}

func render(w http.ResponseWriter, t *template.Template, model interface{}) {
	if err := t.Execute(w, model); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func updateHandler(w http.ResponseWriter, r *http.Request) {

	if err := r.ParseForm(); err != nil {
		http.Error(w, "could not parse form", http.StatusInternalServerError)
		return
	}

	// prefix
	globalModel.Prefix = r.PostForm["prefix"][0]
	// csvFilename
	globalModel.CSVFilename = r.PostForm["csvFilename"][0]
	for _, img := range globalModel.Images {
		// tags
		areaTags := r.PostForm[fmt.Sprintf("image[%d].tags", img.ID)]
		globalModel.Images[img.ID].Tags = strings.Fields(areaTags[0])
		// source
		globalModel.Images[img.ID].Source = r.PostForm[fmt.Sprintf("image[%d].source", img.ID)][0]
		// rating
		rating := r.PostForm[fmt.Sprintf("image[%d].rating", img.ID)]
		if len(rating) != 0 {
			globalModel.Images[img.ID].Rating = rating[0]
		}
	}
	// UseLinuxSep
	_, ok := r.PostForm["useLinuxSep"]
	if ok {
		globalModel.UseLinuxSep = true
	} else {
		globalModel.UseLinuxSep = false
	}
	// scroll
	scroll := r.PostForm["scroll"][0]

	if err := saveToCSVFile(globalModel); err != nil {
		globalModel.Err = fmt.Errorf("Error: could not save to CSV file: %v", err)
		render(w, indexTmpl, globalModel)
	} else {
		globalModel.Err = nil
		http.Redirect(w, r, "/"+scroll, http.StatusFound)
	}
}

func saveToCSVFile(m *model) error {
	csvFilepath := filepath.Join(m.Dir, m.CSVFilename)
	f, err := os.Create(csvFilepath)
	if err != nil {
		return err
	}
	defer func() {
		if cerr := f.Close(); err != nil {
			err = cerr
		}
	}()

	if err := bulk.Save(f, m.Images, m.Dir, m.Prefix, m.UseLinuxSep); err != nil {
		return err
	}
	return err
}

func serveImage(w http.ResponseWriter, r *http.Request) {
	idStr := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:]
	id, err := strconv.Atoi(idStr)
	if err != nil {
		http.Error(w, fmt.Sprintf("%v is not a valid image ID", idStr), http.StatusBadRequest)
		return
	}
	img := bulk.FindByID(globalModel.Images, id)
	if img == nil {
		http.Error(w, fmt.Sprintf("no image found with ID: %v", id), http.StatusNotFound)
		return
	}
	// In case of image name that ends with '.swf', we serve embedded image
	// bytes from swf.go as it's not trivial to display a .swf file.
	if strings.HasSuffix(img.Name, ".swf") {
		_, err = w.Write(swfImageBytes)
		if err != nil {
			http.Error(w, fmt.Sprintf("could not write image bytes: %v", err), http.StatusInternalServerError)
			return
		}
	}

	p := filepath.Join(*directory, img.Name)
	f, err := os.Open(p)
	if err != nil {
		http.Error(w, fmt.Sprintf("could not open image: %v", err), http.StatusInternalServerError)
		return
	}
	defer func() {
		if cerr := f.Close(); cerr != nil {
			log.Printf("Error: could not close image file: %v\n", cerr)
		}
	}()
	data, err := ioutil.ReadAll(f)
	if err != nil {
		http.Error(w, fmt.Sprintf("could not read image: %v", err), http.StatusInternalServerError)
		return
	}
	_, err = w.Write(data)
	if err != nil {
		http.Error(w, fmt.Sprintf("could not write image bytes: %v", err), http.StatusInternalServerError)
		return
	}
}

// startBrowser tries to open the URL in a browser, and returns
// whether it succeed.
func startBrowser(url string) bool {
	// try to start the browser
	var args []string
	switch runtime.GOOS {
	case "darwin":
		args = []string{"open"}
	case "windows":
		args = []string{"cmd", "/c", "start"}
	default:
		args = []string{"xdg-open"}
	}
	cmd := exec.Command(args[0], append(args[1:], url)...)
	return cmd.Start() == nil
}

// waitServer waits some time for the http Server to start
// serving url. The return value reports whether it starts.
func waitServer(url string) bool {
	tries := 20
	for tries > 0 {
		resp, err := http.Get(url)
		if err == nil {
			resp.Body.Close()
			return true
		}
		time.Sleep(100 * time.Millisecond)
		tries--
	}
	return false
}
<|endoftext|>


<commit_before>package main

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

var address = flag.String("address", ":8080", "address to listen on")
var repositories = flag.String("repositories", "scraperwiki/tang", "colon separated list of repositories to watch")

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	flag.Parse()

	configureHooks()

	http.HandleFunc("/hook", handleHook)

	log.Println("Listening on:", *address)
	log.Fatal(http.ListenAndServe(*address, nil))
}

func configureHooks() {
	github_user := os.Getenv("GITHUB_USER")
	github_password := os.Getenv("GITHUB_PASSWORD")

	json := `{
	"name": "web",
	"config": {"url": "http://services.scraperwiki.com/hook",
		"content_type": "json"},
	"events": ["push", "issues", "issue_comment",
		"commit_comment", "create", "delete",
		"pull_request", "pull_request_review_comment",
		"gollum", "watch", "release", "fork", "member",
		"public", "team_add", "status"],
	"active": true
	}`

	endpoint := "https://" + github_user + ":" + github_password + "@" + "api.github.com"

	repos := strings.Split(*repositories, ":")

	for _, repo := range repos {

		buffer := strings.NewReader(json)
		resp, err := http.Post(endpoint+"/repos/"+repo+"/hooks", "application/json", buffer)
		check(err)

		log.Println("Rate Limit:", resp.Header["X-Ratelimit-Remaining"][0])

		switch resp.StatusCode {
		default:
			response, err := ioutil.ReadAll(resp.Body)
			check(err)

			log.Print(string(response))

		case 422:
			log.Println("Already hooked for", repo)
		}
	}

}

type Repository struct {
	Name         string `json:"name"`
	Url          string `json:"url"`
	Organization string `json:"organization"`
}

type PushEvent struct {
	Ref        string     `json:"ref"`
	Repository Repository `json:"repository"`
	After      string     `json:"after"`
}

func handleEvent(eventType string, document []byte) (err error) {

	log.Println("Incoming request:", string(document))

	switch eventType {
	case "push":
		var event PushEvent
		err = json.Unmarshal(document, &event)
		if err != nil {
			return
		}

		err = eventPush(event)
		if err != nil {
			return
		}

	default:
		log.Println("Unhandled event:", eventType)
	}

	return
}

func handleHook(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK\n")

	request, err := ioutil.ReadAll(r.Body)
	check(err)

	var buf bytes.Buffer
	r.Header.Write(&buf)
	log.Println("Incoming request headers: ", string(buf.Bytes()))

	buf.Reset()
	err = json.Indent(&buf, request, "", "  ")
	check(err)

	eventType := r.Header["X-Github-Event"][0]
	data := buf.Bytes()

	err = handleEvent(eventType, data)
	check(err)
}

func Command(workdir, command string, args ...string) *exec.Cmd {
	// log.Printf("wd = %s cmd = %s, args = %q", workdir, command, append([]string{}, args...))
	cmd := exec.Command(command, args...)
	cmd.Dir = workdir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd
}

const GIT_BASE_DIR = "repo"

var (
	ErrEmptyRepoName         = errors.New("Empty repository name")
	ErrEmptyRepoOrganization = errors.New("Empty repository organization")
)

func eventPush(event PushEvent) (err error) {
	if event.Repository.Name == "" {
		return ErrEmptyRepoName
	}
	if event.Repository.Organization == "" {
		return ErrEmptyRepoOrganization
	}

	ref := event.Ref
	url := event.Repository.Url
	after := event.After

	log.Println("Push to", url, ref, "after", after)

	// The name of the subdirectory where the git
	// mirror is (or will appear, if it hasn't been
	// cloned yet).
	git_dir := path.Join(GIT_BASE_DIR, event.Repository.Organization,
		event.Repository.Name)

	err = os.MkdirAll(git_dir, 0777)
	check(err)

	err = Command(".", "git", "clone", "-q", "--mirror", url, git_dir).Run()

	if err == nil {
		log.Println("Cloned", url)

	} else if _, ok := err.(*exec.ExitError); ok {

		// Try "git remote update"
		err := Command(git_dir, "git", "fetch").Run()

		if err != nil {
			// git fetch where there is no update is exit status 1.
			if err.Error() != "exit status 1" {
				check(err)
			}
		}

		log.Println("Remote updated", url)

	} else {
		check(err)
	}

	prefix_dir := path.Join("checkout", after)

	err = os.MkdirAll(path.Join(git_dir, prefix_dir), 0777)
	check(err)

	log.Println("Populating", prefix_dir)

	args := []string{"--work-tree", prefix_dir, "checkout", after, "."}
	err = Command(git_dir, "git", args...).Run()
	check(err)

	log.Println("Created", prefix_dir)

	return
}
<commit_msg>Break up into more functions, improve error handling<commit_after>package main

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

var address = flag.String("address", ":8080", "address to listen on")
var repositories = flag.String("repositories", "scraperwiki/tang", "colon separated list of repositories to watch")

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	flag.Parse()

	configureHooks()

	http.HandleFunc("/hook", handleHook)

	log.Println("Listening on:", *address)
	log.Fatal(http.ListenAndServe(*address, nil))
}

func configureHooks() {
	github_user := os.Getenv("GITHUB_USER")
	github_password := os.Getenv("GITHUB_PASSWORD")

	json := `{
	"name": "web",
	"config": {"url": "http://services.scraperwiki.com/hook",
		"content_type": "json"},
	"events": ["push", "issues", "issue_comment",
		"commit_comment", "create", "delete",
		"pull_request", "pull_request_review_comment",
		"gollum", "watch", "release", "fork", "member",
		"public", "team_add", "status"],
	"active": true
	}`

	endpoint := "https://" + github_user + ":" + github_password + "@" + "api.github.com"

	repos := strings.Split(*repositories, ":")

	for _, repo := range repos {

		buffer := strings.NewReader(json)
		resp, err := http.Post(endpoint+"/repos/"+repo+"/hooks", "application/json", buffer)
		check(err)

		log.Println("Rate Limit:", resp.Header["X-Ratelimit-Remaining"][0])

		switch resp.StatusCode {
		default:
			response, err := ioutil.ReadAll(resp.Body)
			check(err)

			log.Print(string(response))

		case 422:
			log.Println("Already hooked for", repo)
		}
	}

}

type Repository struct {
	Name         string `json:"name"`
	Url          string `json:"url"`
	Organization string `json:"organization"`
}

type PushEvent struct {
	Ref        string     `json:"ref"`
	Repository Repository `json:"repository"`
	After      string     `json:"after"`
}

func handleEvent(eventType string, document []byte) (err error) {

	log.Println("Incoming request:", string(document))

	switch eventType {
	case "push":
		var event PushEvent
		err = json.Unmarshal(document, &event)
		if err != nil {
			return
		}

		err = eventPush(event)
		if err != nil {
			return
		}

	default:
		log.Println("Unhandled event:", eventType)
	}

	return
}

func handleHook(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK\n")

	request, err := ioutil.ReadAll(r.Body)
	check(err)

	var buf bytes.Buffer
	r.Header.Write(&buf)
	log.Println("Incoming request headers: ", string(buf.Bytes()))

	buf.Reset()
	err = json.Indent(&buf, request, "", "  ")
	check(err)

	eventType := r.Header["X-Github-Event"][0]
	data := buf.Bytes()

	err = handleEvent(eventType, data)
	check(err)
}

func Command(workdir, command string, args ...string) *exec.Cmd {
	// log.Printf("wd = %s cmd = %s, args = %q", workdir, command, append([]string{}, args...))
	cmd := exec.Command(command, args...)
	cmd.Dir = workdir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd
}

const GIT_BASE_DIR = "repo"

var (
	ErrEmptyRepoName         = errors.New("Empty repository name")
	ErrEmptyRepoOrganization = errors.New("Empty repository organization")
)

// Creates or updates a mirror of `url` at `git_dir` using `git clone --mirror`
func gitLocalMirror(url, git_dir string) (err error) {

	err = os.MkdirAll(git_dir, 0777)
	if err != nil {
		return
	}

	err = Command(".", "git", "clone", "-q", "--mirror", url, git_dir).Run()

	if err == nil {
		log.Println("Cloned", url)

	} else if _, ok := err.(*exec.ExitError); ok {

		// Try "git remote update"
		err = Command(git_dir, "git", "fetch").Run()

		if err != nil {
			// git fetch where there is no update is exit status 1.
			if err.Error() != "exit status 1" {
				return
			}
		}

		log.Println("Remote updated", url)

	} else {
		return
	}

	return
}

func gitCheckout(git_dir, checkout_dir, ref string) (err error) {

	err = os.MkdirAll(path.Join(git_dir, checkout_dir), 0777)
	if err != nil {
		return
	}

	log.Println("Populating", checkout_dir)

	args := []string{"--work-tree", checkout_dir, "checkout", ref, "."}
	err = Command(git_dir, "git", args...).Run()
	if err != nil {
		return
	}

	return
}

func eventPush(event PushEvent) (err error) {
	if event.Repository.Name == "" {
		return ErrEmptyRepoName
	}
	if event.Repository.Organization == "" {
		return ErrEmptyRepoOrganization
	}

	ref := event.Ref
	url := event.Repository.Url
	after := event.After

	log.Println("Push to", url, ref, "after", after)

	// The name of the subdirectory where the git
	// mirror is (or will appear, if it hasn't been
	// cloned yet).
	git_dir := path.Join(GIT_BASE_DIR, event.Repository.Organization,
		event.Repository.Name)
	err = gitLocalMirror(url, git_dir)
	if err != nil {
		return
	}

	checkout_dir := path.Join("checkout", after)
	err = gitCheckout(git_dir, checkout_dir, after)
	if err != nil {
		return
	}

	log.Println("Created", checkout_dir)

	return
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"

	"github.com/yuya-takeyama/argf"
)

func printErr(err error) {
	fmt.Fprintln(os.Stderr, "rl:", err)
}

func do(rev *Reverser, r io.Reader) error {
	b := bufio.NewScanner(r)
	for b.Scan() {
		fmt.Println(rev.Reverse(b.Text()))
	}
	return b.Err()
}

func _main() int {
	r, err := argf.From(os.Args[1:])
	if err != nil {
		printErr(err)
		return 2
	}

	rev := NewReverser()
	if err = do(rev, r); err != nil {
		printErr(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<commit_msg>Define Option<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"

	"github.com/jessevdk/go-flags"
	"github.com/yuya-takeyama/argf"
)

type Option struct {
	Delimiter string `short:"d" long:"delimiter"`
	isHelp    bool   `          long:"help"`
	isVersion bool   `          long:"version"`
	Files     []string
}

func printErr(err error) {
	fmt.Fprintln(os.Stderr, "rl:", err)
}

func do(rev *Reverser, r io.Reader) error {
	b := bufio.NewScanner(r)
	for b.Scan() {
		fmt.Println(rev.Reverse(b.Text()))
	}
	return b.Err()
}

func _main() int {
	r, err := argf.From(os.Args[1:])
	if err != nil {
		printErr(err)
		return 2
	}

	rev := NewReverser()
	if err = do(rev, r); err != nil {
		printErr(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/intelsdi-x/pulse/control/plugin"
	"github.com/intelsdi-x/pulse/plugin/processor/pulse-processor-movingaverage/movingaverage"
)

func main() {
	meta := movingaverage.Meta()
	plugin.Start(meta, movingaverage.NewMovingaverageProcessor(), os.Args[1])
}
<commit_msg>Update import for movingaverage<commit_after>package main

import (
	"os"

	"github.com/intelsdi-x/pulse-plugin-processor-movingaverage/movingaverage"
	"github.com/intelsdi-x/pulse/control/plugin"
)

func main() {
	meta := movingaverage.Meta()
	plugin.Start(meta, movingaverage.NewMovingaverageProcessor(), os.Args[1])
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"path/filepath"
)

var isVerbose bool
var isQuiet bool

func main() {
	logger.msg("Start.")

	// Parse arguments

	args, err := parseArguments()
	if err != nil {
		outError("Error parsing aruments: %s", err)
		exit(1)
	}

	logger.msg("Arguments passed: %+v", args)

	isVerbose = args["--verbose"].(bool)
	isQuiet = args["--quiet"].(bool)

	var configPath string
	if args["--config"] == nil {
		configPath = ""
	} else {
		configPath = args["--config"].(string)
	}

	// Process arguments
	var rc RC
	if configPath == "" {
		rc, err = readRC()
		if err != nil {
			outError("Error reading rc file: %s", err)
			exit(1)
		}
		if rc.Config.Path == "" {
			outError("Config file not specified.")
			exit(1)
		}
	} else {
		// Save to RC file
		configPath, err = filepath.Abs(configPath)
		if err != nil {
			outError("Bad config path: %s", err)
			exit(1)
		}

		rc, err = saveRC(configPath)
		if err != nil {
			outError("Cannot save rc file: %s", err)
			exit(1)
		}
	}

	// Process config

	config, err := configurationFromFile(rc.Config.Path)
	if err != nil {
		outError("Error reading configuration from file %s: %s", rc.Config.Path, err)
		exit(1)
	}

	// Preparations

	err = os.MkdirAll(config.Directories.Backup, 0755)
	if err != nil && !os.IsExist(err) {
		outError("Error creating backup directory: %s", err)
		exit(1)
	}

	if isVerbose {
		outVerbose("Dotfiles root: %s", config.Directories.Dotfiles)
		outVerbose("Dotfiles src: %s", config.Directories.Sources)
		outVerbose("Destination dir: %s", config.Directories.Destination)
	}

	err = cleanDeadSymlinks(config.Directories.Destination)
	if err != nil {
		outError("Error cleaning dead symlinks: %s", err)
		exit(1)
	}

	srcDirAbs := config.Directories.Dotfiles
	if config.Directories.Sources != "" {
		srcDirAbs += "/" + config.Directories.Sources
	}

	mapping := make(map[string]string)

	if len(config.Mapping) == 0 {
		// install all the things
		outVerbose("Mapping is not specified - install all the things")
		dir, err := os.Open(srcDirAbs)
		if err != nil {
			outError("Error reading dotfiles source dir: %s", err)
			exit(1)
		}

		defer dir.Close()

		files, err := dir.Readdir(0)
		if err != nil {
			outError("Error reading dotfiles source dir: %s", err)
			exit(1)
		}

		for _, fileInfo := range files {
			mapping[fileInfo.Name()] = fileInfo.Name()
		}

		// filter excludes
		for _, exclude := range config.Files.Excludes {
			if _, ok := mapping[exclude]; ok {
				delete(mapping, exclude)
			}
		}
	} else {
		// install by mapping
		if len(config.Files.Excludes) > 0 {
			outWarn("Excludes in config make no sense when mapping is specified, omitting them.")
		}

		mapping = config.Mapping
	}

	outInfo("Installing dotfiles...")
	for src, dest := range mapping {
		srcAbs := srcDirAbs + "/" + src
		destAbs := config.Directories.Destination + "/" + dest

		exists, err := isExists(srcAbs)
		if !exists {
			outWarn("Source file %s does not exist", srcAbs)
			continue
		}

		if err != nil {
			outError("Error processing source file %s: %s", src, err)
			exit(1)
		}

		needSymlink, needBackup, err := processDest(srcAbs, destAbs)
		if err != nil {
			outError("Error processing destination file %s: %s", destAbs, err)
			exit(1)
		}

		if !needSymlink {
			continue
		}

		if needBackup {
			err = backup(dest, destAbs, config.Directories.Backup)
			if err != nil {
				outError("Error backuping file %s: %s", destAbs, err)
				exit(1)
			}
		}

		err = setSymlink(srcAbs, destAbs)
		if err != nil {
			outError("Error creating symlink from %s to %s: %s", srcAbs, destAbs, err)
			exit(1)
		}
	}

	outInfo("All done (─‿‿─)")
	exit(0)
}
<commit_msg>Output error when source dir not exists<commit_after>package main

import (
	"os"
	"path/filepath"
)

var isVerbose bool
var isQuiet bool

func main() {
	logger.msg("Start.")

	// Parse arguments

	args, err := parseArguments()
	if err != nil {
		outError("Error parsing aruments: %s", err)
		exit(1)
	}

	logger.msg("Arguments passed: %+v", args)

	isVerbose = args["--verbose"].(bool)
	isQuiet = args["--quiet"].(bool)

	var configPath string
	if args["--config"] == nil {
		configPath = ""
	} else {
		configPath = args["--config"].(string)
	}

	// Process arguments
	var rc RC
	if configPath == "" {
		rc, err = readRC()
		if err != nil {
			outError("Error reading rc file: %s", err)
			exit(1)
		}
		if rc.Config.Path == "" {
			outError("Config file not specified.")
			exit(1)
		}
	} else {
		// Save to RC file
		configPath, err = filepath.Abs(configPath)
		if err != nil {
			outError("Bad config path: %s", err)
			exit(1)
		}

		rc, err = saveRC(configPath)
		if err != nil {
			outError("Cannot save rc file: %s", err)
			exit(1)
		}
	}

	// Process config

	config, err := configurationFromFile(rc.Config.Path)
	if err != nil {
		outError("Error reading configuration from file %s: %s", rc.Config.Path, err)
		exit(1)
	}

	// Preparations

	err = os.MkdirAll(config.Directories.Backup, 0755)
	if err != nil && !os.IsExist(err) {
		outError("Error creating backup directory: %s", err)
		exit(1)
	}

	if isVerbose {
		outVerbose("Dotfiles root: %s", config.Directories.Dotfiles)
		outVerbose("Dotfiles src: %s", config.Directories.Sources)
		outVerbose("Destination dir: %s", config.Directories.Destination)
	}

	err = cleanDeadSymlinks(config.Directories.Destination)
	if err != nil {
		outError("Error cleaning dead symlinks: %s", err)
		exit(1)
	}

	srcDirAbs := config.Directories.Dotfiles
	if config.Directories.Sources != "" {
		if _, err = os.Stat(config.Directories.Sources); os.IsNotExist(err) {
			outError("Sources directory `%s' does not exist.", config.Directories.Sources)
			exit(1)
		}
		if err != nil {
			outError("Error reading sources directory `%s': %s", config.Directories.Sources, err)
			exit(1)
		}
		srcDirAbs += "/" + config.Directories.Sources
	}

	mapping := make(map[string]string)

	if len(config.Mapping) == 0 {
		// install all the things
		outVerbose("Mapping is not specified - install all the things")
		dir, err := os.Open(srcDirAbs)
		if err != nil {
			outError("Error reading dotfiles source dir: %s", err)
			exit(1)
		}

		defer dir.Close()

		files, err := dir.Readdir(0)
		if err != nil {
			outError("Error reading dotfiles source dir: %s", err)
			exit(1)
		}

		for _, fileInfo := range files {
			mapping[fileInfo.Name()] = fileInfo.Name()
		}

		// filter excludes
		for _, exclude := range config.Files.Excludes {
			if _, ok := mapping[exclude]; ok {
				delete(mapping, exclude)
			}
		}
	} else {
		// install by mapping
		if len(config.Files.Excludes) > 0 {
			outWarn("Excludes in config make no sense when mapping is specified, omitting them.")
		}

		mapping = config.Mapping
	}

	outInfo("Installing dotfiles...")
	for src, dest := range mapping {
		srcAbs := srcDirAbs + "/" + src
		destAbs := config.Directories.Destination + "/" + dest

		exists, err := isExists(srcAbs)
		if !exists {
			outWarn("Source file %s does not exist", srcAbs)
			continue
		}

		if err != nil {
			outError("Error processing source file %s: %s", src, err)
			exit(1)
		}

		needSymlink, needBackup, err := processDest(srcAbs, destAbs)
		if err != nil {
			outError("Error processing destination file %s: %s", destAbs, err)
			exit(1)
		}

		if !needSymlink {
			continue
		}

		if needBackup {
			err = backup(dest, destAbs, config.Directories.Backup)
			if err != nil {
				outError("Error backuping file %s: %s", destAbs, err)
				exit(1)
			}
		}

		err = setSymlink(srcAbs, destAbs)
		if err != nil {
			outError("Error creating symlink from %s to %s: %s", srcAbs, destAbs, err)
			exit(1)
		}
	}

	outInfo("All done (─‿‿─)")
	exit(0)
}
<|endoftext|>


<commit_before>// auto-mywire is a program to maintain the connection to mywire.
package main

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	pingURL  = "www.google.com"
	loginURL = "https://login.my-wire.de/index.php"

	// waitTime in seconds if mywire tells us to wait
	waitTime = 2

	// startStr and endStr determine where the mywire response is to be found
	startStr = `<div id="content_popup">`
	endStr   = `</div>`

	confUser = "AUTO_MYWIRE_USER"
	confPass = "AUTO_MYWIRE_PASS"
)

func readUserAndPass() (user, pass string) {
	user = os.Getenv(confUser)
	if user == "" {
		fmt.Printf("Fatal error: environment variable %v not set.\n", confUser)
		os.Exit(1)
	}

	pass = os.Getenv(confPass)
	if pass == "" {
		fmt.Printf("Fatal error: environment variable %v not set.\n", confPass)
		os.Exit(1)
	}

	return
}

type mywireStatus int

const (
	mywireUnknown mywireStatus = iota
	mywireSuccess
	mywireFailure
	mywireWait
)

func login(user, pass string) (status mywireStatus, err error) {
	resp, err := http.PostForm(loginURL, url.Values{
		"user":   {user},
		"pass":   {pass},
		"action": {"login"},
	})
	if err != nil {
		return
	}
	defer resp.Body.Close()

	r := bufio.NewReader(resp.Body)
	for {
		line, err := r.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				err = nil
				break
			}
			return mywireUnknown, err
		}

		if strings.Contains(line, startStr) {
			if !strings.Contains(line, endStr) {
				// If this happens, you have to update this application
				return mywireUnknown, fmt.Errorf("unknown response format")
			}

			if strings.Contains(line, "WARTEN") {
				return mywireWait, nil
			} else if strings.Contains(line, "ERFOLGREICH") {
				return mywireSuccess, nil
			} else {
				// Find out what the mywire response actually is
				start := strings.Index(line, startStr) + len(startStr)
				end := strings.LastIndex(line, endStr)
				msg := line[start:end]
				return mywireFailure, fmt.Errorf(msg)
			}
		}
	}

	return mywireUnknown, fmt.Errorf("failure reading mywire response")
}

func isOnline(path string) (online, mywire bool) {
	catch := fmt.Errorf("detected my-wire.de redirect")

	c := &http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error {
		if strings.Contains(req.URL.Path, "my-wire.de") {
			return catch
		}
		return nil
	}}

	resp, err := c.Get(path)
	if resp != nil && resp.Close {
		resp.Body.Close()
	}
	return err != nil, err == catch
}

func main() {
	fmt.Printf("Checking online connectivity... ")
	online, mywire := isOnline(pingURL)
	if online {
		fmt.Println("success.")
		return
	}
	fmt.Println("failed.")
	if !mywire {
		fmt.Println("Error: mywire service not available for login process.")
		os.Exit(1)
	}

	user, pass := readUserAndPass()
	for {
		resp, err := login(user, pass)
		switch resp {
		case mywireWait:
			// This is the only case where the loop continues
			fmt.Printf("Waiting %v seconds...\n", waitTime)
			time.Sleep(waitTime * time.Second)
		case mywireSuccess:
			if online, _ = isOnline(pingURL); online {
				fmt.Println("ONLINE")
				return
			} else {
				fmt.Println("Fatal error: mywire response indicates success, but still no connectivity.")
				os.Exit(1)
			}
		case mywireFailure:
			fmt.Printf("Fatal error: mywire responded, %v\n", err)
			os.Exit(1)
		default:
			fmt.Printf("Fatal error: %v.\n", err)
			os.Exit(1)
		}
	}
}
<commit_msg>Renaming environment variables from AUTO_(.*) to \1<commit_after>// auto-mywire is a program to maintain the connection to mywire.
package main

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	pingURL  = "www.google.com"
	loginURL = "https://login.my-wire.de/index.php"

	// waitTime in seconds if mywire tells us to wait
	waitTime = 2

	// startStr and endStr determine where the mywire response is to be found
	startStr = `<div id="content_popup">`
	endStr   = `</div>`

	confUser = "MYWIRE_USER"
	confPass = "MYWIRE_PASS"
)

func readUserAndPass() (user, pass string) {
	user = os.Getenv(confUser)
	if user == "" {
		fmt.Printf("Fatal error: environment variable %v not set.\n", confUser)
		os.Exit(1)
	}

	pass = os.Getenv(confPass)
	if pass == "" {
		fmt.Printf("Fatal error: environment variable %v not set.\n", confPass)
		os.Exit(1)
	}

	return
}

type mywireStatus int

const (
	mywireUnknown mywireStatus = iota
	mywireSuccess
	mywireFailure
	mywireWait
)

func login(user, pass string) (status mywireStatus, err error) {
	resp, err := http.PostForm(loginURL, url.Values{
		"user":   {user},
		"pass":   {pass},
		"action": {"login"},
	})
	if err != nil {
		return
	}
	defer resp.Body.Close()

	r := bufio.NewReader(resp.Body)
	for {
		line, err := r.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				err = nil
				break
			}
			return mywireUnknown, err
		}

		if strings.Contains(line, startStr) {
			if !strings.Contains(line, endStr) {
				// If this happens, you have to update this application
				return mywireUnknown, fmt.Errorf("unknown response format")
			}

			if strings.Contains(line, "WARTEN") {
				return mywireWait, nil
			} else if strings.Contains(line, "ERFOLGREICH") {
				return mywireSuccess, nil
			} else {
				// Find out what the mywire response actually is
				start := strings.Index(line, startStr) + len(startStr)
				end := strings.LastIndex(line, endStr)
				msg := line[start:end]
				return mywireFailure, fmt.Errorf(msg)
			}
		}
	}

	return mywireUnknown, fmt.Errorf("failure reading mywire response")
}

func isOnline(path string) (online, mywire bool) {
	catch := fmt.Errorf("detected my-wire.de redirect")

	c := &http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error {
		if strings.Contains(req.URL.Path, "my-wire.de") {
			return catch
		}
		return nil
	}}

	resp, err := c.Get(path)
	if resp != nil && resp.Close {
		resp.Body.Close()
	}
	return err != nil, err == catch
}

func main() {
	fmt.Printf("Checking online connectivity... ")
	online, mywire := isOnline(pingURL)
	if online {
		fmt.Println("success.")
		return
	}
	fmt.Println("failed.")
	if !mywire {
		fmt.Println("Error: mywire service not available for login process.")
		os.Exit(1)
	}

	user, pass := readUserAndPass()
	for {
		resp, err := login(user, pass)
		switch resp {
		case mywireWait:
			// This is the only case where the loop continues
			fmt.Printf("Waiting %v seconds...\n", waitTime)
			time.Sleep(waitTime * time.Second)
		case mywireSuccess:
			if online, _ = isOnline(pingURL); online {
				fmt.Println("ONLINE")
				return
			} else {
				fmt.Println("Fatal error: mywire response indicates success, but still no connectivity.")
				os.Exit(1)
			}
		case mywireFailure:
			fmt.Printf("Fatal error: mywire responded, %v\n", err)
			os.Exit(1)
		default:
			fmt.Printf("Fatal error: %v.\n", err)
			os.Exit(1)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"

	"github.com/BurntSushi/toml"
	"github.com/PuerkitoBio/goquery"
	"github.com/fatih/color"
	"github.com/mitchellh/go-homedir"
	"github.com/urfave/cli"
)

var (
	Version  string
	Revision string
)

type configFile struct {
	Urls      []string `toml:"urls"`
	UserAgent string   `toml:"useragent"`
}

type requestSetting struct {
	url       string
	useragent string
	redirect  bool
}

func main() {
	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
	}
	home, err := homedir.Dir()
	if err != nil {
		return
	}
	dir := filepath.Join(home, ".config", "gocrawsan")
	if err = os.MkdirAll(dir, 0700); err != nil {
		return
	}
	app := cli.NewApp()
	app.Name = "gocrawsan"
	app.Usage = "web crawling command utility"
	app.Version = Version
	app.Usage = ""
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "useragent, U",
		},
		cli.StringFlag{
			Name: "config, C",
			Value: filepath.Join(dir, "config.toml"),
		},
		cli.BoolFlag{
			Name: "redirect",
		},
		cli.BoolFlag{
			Name: "debug, D",
		},
	}
	app.Action = crawling
	app.Run(os.Args)
}

func crawling(c *cli.Context) error {
	wg := new(sync.WaitGroup)
	m := new(sync.Mutex)

	ua := c.String("useragent")
	buf, err := ioutil.ReadFile(c.String("config"))
	if err != nil {
		return err
	}
	file := &configFile{}
	err = toml.Unmarshal(buf, file)
	if err != nil {
		return err
	}

	for _, url := range file.Urls {
		wg.Add(1)
		s := &requestSetting{
			url:       url,
			useragent: ua,
			redirect:  c.Bool("redirect"),
		}
		go getUrl(wg, m, s, 1)
	}
	wg.Wait()
	return nil
}

func getUrl(wg *sync.WaitGroup, m *sync.Mutex, s *requestSetting, d int) {
	client := &http.Client{}
	if s.redirect {
		client.CheckRedirect = func (req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
		}
	}
	req, _ := http.NewRequest("GET", s.url, nil)
	req.Header.Set("User-Agent", s.useragent)

	resp, _ := client.Do(req)
	status := strings.Split(resp.Status, " ")
	code, _ := strconv.Atoi(status[0])
	d -= 1

	m.Lock()
	fmt.Print(s.url + "\t")

	switch code / 100 {
	case 2:
		color.Cyan(resp.Status)
	case 3:
		color.Yellow(resp.Status)
	case 4:
		color.Red(resp.Status)
	default:
		fmt.Println(resp.Status)
	}
	m.Unlock()
	if d > 0 {
		_, _ = getLinks(resp)
	}
	wg.Done()
}

func getLinks(res *http.Response) ([]string, error) {
	urls := []string{}
	doc, _ := goquery.NewDocumentFromResponse(res)
	doc.Find("a").Each(func(_ int, s *goquery.Selection) {
		url, _ := s.Attr("href")
		r := regexp.MustCompile(`^(https|http)://(.*)`)
		if !r.MatchString(url) {
			url = res.Request.URL.Scheme + "://" + res.Request.URL.Host + url
		}
		urls = append(urls, url)
	})
	return urls, nil
}
<commit_msg>Refactoring<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"

	"github.com/BurntSushi/toml"
	"github.com/PuerkitoBio/goquery"
	"github.com/fatih/color"
	"github.com/mitchellh/go-homedir"
	"github.com/urfave/cli"
)

var (
	Version  string
	Revision string
)

type configFile struct {
	Urls      []string `toml:"urls"`
	UserAgent string   `toml:"useragent"`
}

type requestSetting struct {
	url       string
	useragent string
	redirect  bool
}

func main() {
	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
	}
	home, err := homedir.Dir()
	if err != nil {
		return
	}
	dir := filepath.Join(home, ".config", "gocrawsan")
	if err = os.MkdirAll(dir, 0700); err != nil {
		return
	}
	app := cli.NewApp()
	app.Name = "gocrawsan"
	app.Usage = "web crawling command utility"
	app.Version = Version
	app.Usage = ""
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "useragent, U",
		},
		cli.StringFlag{
			Name: "config, C",
			Value: filepath.Join(dir, "config.toml"),
		},
		cli.BoolFlag{
			Name: "redirect",
		},
		cli.BoolFlag{
			Name: "debug, D",
		},
	}
	app.Action = func (c *cli.Context) error {
		cr := NewCrawler()
		ua := c.String("useragent")
		cr.useragent = ua
		cr.redirect = c.Bool("redirect")
		buf, err := ioutil.ReadFile(c.String("config"))
		if err != nil {
			return err
		}
		file := &configFile{}
		err = toml.Unmarshal(buf, file)
		if err != nil {
			return err
		}
		cr.crawling(file.Urls)
		return nil
	}
	app.Run(os.Args)
}

type Crawler struct {
	m *sync.Mutex
	wg *sync.WaitGroup
	useragent string
	redirect bool
}

func NewCrawler() *Crawler {
	c := &Crawler{
		wg: new(sync.WaitGroup),
		m: new(sync.Mutex),
	}
	return c
}

func (c *Crawler) crawling(urls []string) error {
	for _, url := range urls {
		c.wg.Add(1)
		go c.getUrl(url, c.printHttpStatus, 1)
	}
	c.wg.Wait()
	return nil
}

func (c *Crawler) getUrl(url string, f func(string, *http.Response), d int) {
	client := &http.Client{}
	if c.redirect {
		client.CheckRedirect = func (req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse
		}
	}
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("User-Agent", c.useragent)

	resp, _ := client.Do(req)
	d -= 1
	f(url, resp)
	c.accessToNext(resp, d)
	c.wg.Done()
}

func (c *Crawler) printHttpStatus(url string, resp *http.Response) {
	c.m.Lock()
	status := strings.Split(resp.Status, " ")
	code, _ := strconv.Atoi(status[0])
	fmt.Print(url + "\t")
	switch code / 100 {
	case 2:
		color.Cyan(resp.Status)
	case 3:
		color.Yellow(resp.Status)
	case 4:
		color.Red(resp.Status)
	default:
		fmt.Println(resp.Status)
	}
	c.m.Unlock()
}

func (c *Crawler) accessToNext(resp *http.Response, d int) {
	if d > 0 {
		links, err := getLinks(resp)
    if err == nil {
      for _, link := range links {
        c.wg.Add(1)
        go c.getUrl(link, c.printHttpStatus, d)
      }
    }
	}
}
func getLinks(res *http.Response) ([]string, error) {
	urls := []string{}
	doc, _ := goquery.NewDocumentFromResponse(res)
	doc.Find("a").Each(func(_ int, s *goquery.Selection) {
		url, _ := s.Attr("href")
		r := regexp.MustCompile(`^(https|http)://(.*)`)
		if !r.MatchString(url) {
			url = res.Request.URL.Scheme + "://" + res.Request.URL.Host + url
		}
		urls = append(urls, url)
	})
	return urls, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/rs/cors"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"golang.org/x/oauth2/jwt"
	"google.golang.org/api/calendar/v3"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"time"
)

func main() {
	//	Set up our flags
	port := flag.Int("port", 3000, "The port to listen on")
	authEmail := flag.String("authEmail", "ReplaceWithSvcAcctEmail", "Service account email address")
	authSubject := flag.String("authSubject", "user@domain.com", "Impersonated user email address")

	//	Parse the command line for flags:
	flag.Parse()

	//	Read the key file in:
	keydata, err := ioutil.ReadFile("key.pem")
	if err != nil {
		log.Fatal(err)
	}

	// Your credentials should be obtained from the Google
	// Developer Console (https://console.developers.google.com).
	conf := &jwt.Config{
		Email: *authEmail,
		// The contents of your RSA private key or your PEM file
		// that contains a private key.
		// If you have a p12 file instead, you
		// can use `openssl` to export the private key into a pem file.
		//
		//    $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
		//
		// The field only supports PEM containers with no passphrase.
		// The openssl command will convert p12 keys to passphrase-less PEM containers.
		PrivateKey: keydata,
		Scopes: []string{
			calendar.CalendarScope,
			calendar.CalendarReadonlyScope,
		},
		TokenURL: google.JWTTokenURL,
		// If you would like to impersonate a user, you can
		// create a transport with a subject. The following GET
		// request will be made on the behalf of user@example.com.
		// Optional.
		Subject: *authSubject,
	}

	// Initiate an http.Client, the following GET request will be
	// authorized and authenticated on the behalf of user@example.com.
	client := conf.Client(oauth2.NoContext)

	r := mux.NewRouter()
	r.HandleFunc("/calendar/{calendarid}", func(w http.ResponseWriter, r *http.Request) {

		//	Parse the calendarid from the url
		id := mux.Vars(r)["calendarid"]

		//	Get a connection to the calendar service
		//	If we have errors, return them using standard HTTP service method
		svc, err := calendar.New(client)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		//	Get the list of events from now until the end of today
		events, err := svc.Events.List(id).
			TimeMin(time.Now().Format(time.RFC3339)).
			TimeMax(time.Now().Truncate(24 * time.Hour).Add(24 * time.Hour).Format(time.RFC3339)).
			SingleEvents(true).
			OrderBy("startTime").Do()

		//	If we have errors, return them using standard HTTP service method
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		//	Set the content type header and return the JSON
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(events)
	})

	//	CORS handler
	handler := cors.Default().Handler(r)

	//	Indicate what port we're starting the service on
	portString := strconv.Itoa(*port)
	fmt.Println("Starting server on :", portString)
	http.ListenAndServe(":"+portString, handler)
}
<commit_msg>Fixed bug with time calculation<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/rs/cors"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"golang.org/x/oauth2/jwt"
	"google.golang.org/api/calendar/v3"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"time"
)

func main() {
	//	Set up our flags
	port := flag.Int("port", 3000, "The port to listen on")
	authEmail := flag.String("authEmail", "ReplaceWithSvcAcctEmail", "Service account email address")
	authSubject := flag.String("authSubject", "user@domain.com", "Impersonated user email address")

	//	Parse the command line for flags:
	flag.Parse()

	//	Read the key file in:
	keydata, err := ioutil.ReadFile("key.pem")
	if err != nil {
		log.Fatal(err)
	}

	// Your credentials should be obtained from the Google
	// Developer Console (https://console.developers.google.com).
	conf := &jwt.Config{
		Email: *authEmail,
		// The contents of your RSA private key or your PEM file
		// that contains a private key.
		// If you have a p12 file instead, you
		// can use `openssl` to export the private key into a pem file.
		//
		//    $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
		//
		// The field only supports PEM containers with no passphrase.
		// The openssl command will convert p12 keys to passphrase-less PEM containers.
		PrivateKey: keydata,
		Scopes: []string{
			calendar.CalendarScope,
			calendar.CalendarReadonlyScope,
		},
		TokenURL: google.JWTTokenURL,
		// If you would like to impersonate a user, you can
		// create a transport with a subject. The following GET
		// request will be made on the behalf of user@example.com.
		// Optional.
		Subject: *authSubject,
	}

	// Initiate an http.Client, the following GET request will be
	// authorized and authenticated on the behalf of user@example.com.
	client := conf.Client(oauth2.NoContext)

	r := mux.NewRouter()
	r.HandleFunc("/calendar/{calendarid}", func(w http.ResponseWriter, r *http.Request) {

		//	Parse the calendarid from the url
		id := mux.Vars(r)["calendarid"]

		//	Get a connection to the calendar service
		//	If we have errors, return them using standard HTTP service method
		svc, err := calendar.New(client)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		//	Get the list of events from now until the end of today
		now := time.Now()
		end := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).Add(24 * time.Hour)

		events, err := svc.Events.List(id).
			TimeMin(now.Format(time.RFC3339)).
			TimeMax(end.Format(time.RFC3339)).
			SingleEvents(true).
			OrderBy("startTime").Do()

		//	If we have errors, return them using standard HTTP service method
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		//	Set the content type header and return the JSON
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(events)
	})

	//	CORS handler
	handler := cors.Default().Handler(r)

	//	Indicate what port we're starting the service on
	portString := strconv.Itoa(*port)
	fmt.Println("Starting server on :", portString)
	http.ListenAndServe(":"+portString, handler)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	bin "encoding/binary"
	"fmt"
	"log"
	"math"
	"os"
	"strings"
	"time"
)

const (
	Wpm  = 20.0      //words per minutes
	Tone = 700       //frequency in Hertz
	Sps  = 1000      //samples per seconds
	Eps  = Wpm / 1.2 //elements per second (frequency of morse coding)
	Bit  = 1.2 / Wpm //seconds per element (period of morse coding)
)

//directly compare byte for optimization
var m = map[string]string{
	":":  "---...",
	"?":  "..--..",
	"'":  ".----.",
	"/":  "-..-.",
	"(":  "-.--.-",
	")":  "-.--.-",
	"\"": ".-..-.",
	"@":  ".--.-.",
	"=":  "-...-",
	"-":  "-....-",
	",":  "--..--",
	".":  ".-.-.-",
	" ":  "/",
	"A":  ".-",
	"B":  "-...",
	"C":  "-.-.",
	"D":  "-..",
	"E":  ".",
	"F":  "..-.",
	"G":  "--.",
	"H":  "....",
	"I":  "..",
	"J":  ".---",
	"K":  "-.-",
	"L":  ".-..",
	"M":  "--",
	"N":  "-.",
	"O":  "---",
	"P":  ".--.",
	"Q":  "--.-",
	"R":  ".-.",
	"S":  "...",
	"T":  "-",
	"U":  "..-",
	"V":  "...-",
	"W":  ".--",
	"X":  "-..-",
	"Y":  "-.--",
	"Z":  "--..",
	"0":  "-----",
	"1":  ".----",
	"2":  "..---",
	"3":  "...--",
	"4":  "....-",
	"5":  ".....",
	"6":  "-....",
	"7":  "--...",
	"8":  "---..",
	"9":  "----.",
}

func main() {

	filename := os.Args[1]

	inputFile, err := os.Open(filename)
	if err != nil {
		log.Fatal("Error opening input file:", err)
	}

	defer inputFile.Close()

	scanner := bufio.NewScanner(inputFile)

	var message string

	for scanner.Scan() {
		message += scanner.Text()
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(scanner.Err())
	}
	start := time.Now()
	morseCode := translateRuneToMorse(message)
	go fmt.Println(morseCode)

	freqSlice := translateMorseToFreq(morseCode)

	data := translateFreqToData(freqSlice)

	writeWave("morse.wav", Sps, data)
	elapsed := time.Since(start)
	fmt.Println(elapsed)
}

func translateRuneToMorse(input string) string {
	var morseCode string
	for _, r := range input {
		char := strings.ToUpper(string(r))
		if val, ok := m[char]; ok {
			morseCode += val + " "
		}
	}
	return morseCode
}

func translateMorseToFreq(input string) []int {
	var freqSlice []int
	for _, c := range input {
		if c == '.' {
			freqSlice = append(freqSlice, 1, 0)
		} else if c == '-' {
			freqSlice = append(freqSlice, 1, 1, 1, 0)
		} else if c == ' ' {
			freqSlice = append(freqSlice, 0, 0) //end of letter
		}
	}
	freqSlice = append(freqSlice, 0, 0, 0, 0) //end of word
	return freqSlice
}

func translateFreqToData(input []int) []int16 {
	var data []int16

	ampl := 0.85 * 32767
	pi := 3.1415926535
	w := 2.0 * pi * Tone
	var i, n int32

	n = int32(Bit * Sps)
	for _, freq := range input {
		for i = 0; i < n; i += 1 {
			t := float64(i) / Sps
			data = append(data, int16(freq)*int16(ampl*math.Sin(w*t)))
		}
	}

	return data
}

func writeWave(fn string, sample_rate int, data []int16) {
	file, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal("Error opening file for writing: %v\n", err)
	}

	var header Wav

	header.ChunkID = [4]byte{'R', 'I', 'F', 'F'}
	header.Format = [4]byte{'W', 'A', 'V', 'E'}
	header.Subchunk1ID = [4]byte{'f', 'm', 't', ' '}
	header.Subchunk1Size = 16
	header.AudioFormat = 1 // 1 == PCM
	header.NumChannels = 2 // 2 == Stereo
	header.SampleRate = uint32(sample_rate)
	header.BitsPerSample = 16 // 16bit integer samples
	header.ByteRate = uint32(int(header.SampleRate) * int(header.NumChannels) * int(header.BitsPerSample/8))
	header.BlockAlign = uint16(int(header.NumChannels) * int(header.BitsPerSample/8))
	header.Subchunk2ID = [4]byte{'d', 'a', 't', 'a'}

	header.Subchunk2Size = uint32(len(data) * int(header.BitsPerSample/8))
	header.ChunkSize = 4 + (8 + header.Subchunk1Size) + (8 + header.Subchunk2Size)

	bin.Write(file, bin.BigEndian, &header.ChunkID)
	bin.Write(file, bin.LittleEndian, &header.ChunkSize)
	bin.Write(file, bin.BigEndian, &header.Format)

	bin.Write(file, bin.BigEndian, &header.Subchunk1ID)
	bin.Write(file, bin.LittleEndian, &header.Subchunk1Size)
	bin.Write(file, bin.LittleEndian, &header.AudioFormat)
	bin.Write(file, bin.LittleEndian, &header.NumChannels)
	bin.Write(file, bin.LittleEndian, &header.SampleRate)
	bin.Write(file, bin.LittleEndian, &header.ByteRate)
	bin.Write(file, bin.LittleEndian, &header.BlockAlign)
	bin.Write(file, bin.LittleEndian, &header.BitsPerSample)

	bin.Write(file, bin.BigEndian, &header.Subchunk2ID)
	bin.Write(file, bin.LittleEndian, &header.Subchunk2Size)

	bin.Write(file, bin.LittleEndian, data)

	file.Close()

	return
}
<commit_msg>remove comments<commit_after>package main

import (
	"bufio"
	bin "encoding/binary"
	"fmt"
	"log"
	"math"
	"os"
	"strings"
	"time"
)

const (
	Wpm  = 20.0      //words per minutes
	Tone = 700       //frequency in Hertz
	Sps  = 1000      //samples per seconds
	Eps  = Wpm / 1.2 //elements per second (frequency of morse coding)
	Bit  = 1.2 / Wpm //seconds per element (period of morse coding)
)

var m = map[string]string{
	":":  "---...",
	"?":  "..--..",
	"'":  ".----.",
	"/":  "-..-.",
	"(":  "-.--.-",
	")":  "-.--.-",
	"\"": ".-..-.",
	"@":  ".--.-.",
	"=":  "-...-",
	"-":  "-....-",
	",":  "--..--",
	".":  ".-.-.-",
	" ":  "/",
	"A":  ".-",
	"B":  "-...",
	"C":  "-.-.",
	"D":  "-..",
	"E":  ".",
	"F":  "..-.",
	"G":  "--.",
	"H":  "....",
	"I":  "..",
	"J":  ".---",
	"K":  "-.-",
	"L":  ".-..",
	"M":  "--",
	"N":  "-.",
	"O":  "---",
	"P":  ".--.",
	"Q":  "--.-",
	"R":  ".-.",
	"S":  "...",
	"T":  "-",
	"U":  "..-",
	"V":  "...-",
	"W":  ".--",
	"X":  "-..-",
	"Y":  "-.--",
	"Z":  "--..",
	"0":  "-----",
	"1":  ".----",
	"2":  "..---",
	"3":  "...--",
	"4":  "....-",
	"5":  ".....",
	"6":  "-....",
	"7":  "--...",
	"8":  "---..",
	"9":  "----.",
}

func main() {

	filename := os.Args[1]

	inputFile, err := os.Open(filename)
	if err != nil {
		log.Fatal("Error opening input file:", err)
	}

	defer inputFile.Close()

	scanner := bufio.NewScanner(inputFile)

	var message string

	for scanner.Scan() {
		message += scanner.Text()
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(scanner.Err())
	}
	start := time.Now()
	morseCode := translateRuneToMorse(message)
	go fmt.Println(morseCode)

	freqSlice := translateMorseToFreq(morseCode)

	data := translateFreqToData(freqSlice)

	writeWave("morse.wav", Sps, data)
	elapsed := time.Since(start)
	fmt.Println(elapsed)
}

func translateRuneToMorse(input string) string {
	var morseCode string
	for _, r := range input {
		char := strings.ToUpper(string(r))
		if val, ok := m[char]; ok {
			morseCode += val + " "
		}
	}
	return morseCode
}

func translateMorseToFreq(input string) []int {
	var freqSlice []int
	for _, c := range input {
		if c == '.' {
			freqSlice = append(freqSlice, 1, 0)
		} else if c == '-' {
			freqSlice = append(freqSlice, 1, 1, 1, 0)
		} else if c == ' ' {
			freqSlice = append(freqSlice, 0, 0) //end of letter
		}
	}
	freqSlice = append(freqSlice, 0, 0, 0, 0) //end of word
	return freqSlice
}

func translateFreqToData(input []int) []int16 {
	var data []int16

	ampl := 0.85 * 32767
	pi := 3.1415926535
	w := 2.0 * pi * Tone
	var i, n int32

	n = int32(Bit * Sps)
	for _, freq := range input {
		for i = 0; i < n; i += 1 {
			t := float64(i) / Sps
			data = append(data, int16(freq)*int16(ampl*math.Sin(w*t)))
		}
	}

	return data
}

func writeWave(fn string, sample_rate int, data []int16) {
	file, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal("Error opening file for writing: %v\n", err)
	}

	var header Wav

	header.ChunkID = [4]byte{'R', 'I', 'F', 'F'}
	header.Format = [4]byte{'W', 'A', 'V', 'E'}
	header.Subchunk1ID = [4]byte{'f', 'm', 't', ' '}
	header.Subchunk1Size = 16
	header.AudioFormat = 1 // 1 == PCM
	header.NumChannels = 2 // 2 == Stereo
	header.SampleRate = uint32(sample_rate)
	header.BitsPerSample = 16 // 16bit integer samples
	header.ByteRate = uint32(int(header.SampleRate) * int(header.NumChannels) * int(header.BitsPerSample/8))
	header.BlockAlign = uint16(int(header.NumChannels) * int(header.BitsPerSample/8))
	header.Subchunk2ID = [4]byte{'d', 'a', 't', 'a'}

	header.Subchunk2Size = uint32(len(data) * int(header.BitsPerSample/8))
	header.ChunkSize = 4 + (8 + header.Subchunk1Size) + (8 + header.Subchunk2Size)

	bin.Write(file, bin.BigEndian, &header.ChunkID)
	bin.Write(file, bin.LittleEndian, &header.ChunkSize)
	bin.Write(file, bin.BigEndian, &header.Format)

	bin.Write(file, bin.BigEndian, &header.Subchunk1ID)
	bin.Write(file, bin.LittleEndian, &header.Subchunk1Size)
	bin.Write(file, bin.LittleEndian, &header.AudioFormat)
	bin.Write(file, bin.LittleEndian, &header.NumChannels)
	bin.Write(file, bin.LittleEndian, &header.SampleRate)
	bin.Write(file, bin.LittleEndian, &header.ByteRate)
	bin.Write(file, bin.LittleEndian, &header.BlockAlign)
	bin.Write(file, bin.LittleEndian, &header.BitsPerSample)

	bin.Write(file, bin.BigEndian, &header.Subchunk2ID)
	bin.Write(file, bin.LittleEndian, &header.Subchunk2Size)

	bin.Write(file, bin.LittleEndian, data)

	file.Close()

	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"

	"log"
	"os"
	"os/exec"
	"strings"

	"net/http"
)

var repoCommands = make(map[string][]string)

// DockerHubPayload is (partially) the webhook produced when a build completes on hub.docker.com
type DockerHubPayload struct {
	CallbackURL string              `json:"callback_url,omitempty"`
	Repository  DockerHubRepository `json:"repository,omitempty"`
	// There are a lot more fields, only putting in the ones I needed right now
	// Submit a PR if you'd like to see more
}

// DockerHubRepository Some of the pertinent bits that we'll use
type DockerHubRepository struct {
	Name      string `json:"name,omitempty"`
	Namespace string `json:"namespace,omitempty"`
	Owner     string `json:"owner,omitempty"`
	RepoName  string `json:"repo_name,omitempty"`
}

// DockerHubHandler accepts the webhook payload as produced when a build completes on hub.docker.com
func DockerHubHandler(rw http.ResponseWriter, req *http.Request) {

	decoder := json.NewDecoder(req.Body)
	var dockerHubPayload DockerHubPayload
	err := decoder.Decode(&dockerHubPayload)

	if err != nil {
		log.Println("Unable to read payload as JSON")
		log.Println(err)
		return
	}

	repo := dockerHubPayload.Repository.RepoName
	command, ok := repoCommands[repo]

	if !ok { // || len(command) == 0 {
		log.Printf("Repository \"%s\" not enabled\n", repo)
		return
	}

	log.Println("Processing", repo)
	log.Println("Running", command)

	repoCmd := exec.Command(command[0], command[1:]...)

	output, err := repoCmd.Output()
	if err != nil {
		panic(err)
	}

	log.Println(string(output))

}

func main() {

	// Accept all environment variables starting with AUTODOCK_ as configuration
	// for autodock. We're doing this instead of using flags because of how the
	// google/golang-runtime image works (no command line arguments).
	for _, e := range os.Environ() {
		pair := strings.Split(e, "=")
		key := pair[0]
		if strings.Contains(key, "AUTODOCK_") {
			autodockit := os.Getenv(key)
			autodocksplit := strings.Split(autodockit, ":")

			repo := autodocksplit[0]
			commands := strings.Join(autodocksplit[1:], ":")

			// Lazy mode, accepting spaces as delimiters between command arguments
			repoCommands[repo] = strings.Split(commands, " ")

		}
	}

	if len(repoCommands) == 0 {
		panic("No repositories configured")
	}

	log.Println("Docker repository actions:")
	for repo, commands := range repoCommands {
		log.Printf("\t%s: %s\n", repo, commands)
	}

	// TODO: Print out the full URL for the webhook on registry.hub.docker.com
	// TODO: Determine IP of the public host?
	log.Println("Point your Hook config at: http://{IP}/autodock/v1/")

	http.HandleFunc("/autodock/v1/", DockerHubHandler)
	http.ListenAndServe(":8080", nil)
}
<commit_msg>List IP and Port<commit_after>package main

import (
	"encoding/json"

	"log"
	"os"
	"os/exec"
	"strings"

	"net/http"
)

var repoCommands = make(map[string][]string)

// DockerHubPayload is (partially) the webhook produced when a build completes on hub.docker.com
type DockerHubPayload struct {
	CallbackURL string              `json:"callback_url,omitempty"`
	Repository  DockerHubRepository `json:"repository,omitempty"`
	// There are a lot more fields, only putting in the ones I needed right now
	// Submit a PR if you'd like to see more
}

// DockerHubRepository Some of the pertinent bits that we'll use
type DockerHubRepository struct {
	Name      string `json:"name,omitempty"`
	Namespace string `json:"namespace,omitempty"`
	Owner     string `json:"owner,omitempty"`
	RepoName  string `json:"repo_name,omitempty"`
}

// DockerHubHandler accepts the webhook payload as produced when a build completes on hub.docker.com
func DockerHubHandler(rw http.ResponseWriter, req *http.Request) {

	decoder := json.NewDecoder(req.Body)
	var dockerHubPayload DockerHubPayload
	err := decoder.Decode(&dockerHubPayload)

	if err != nil {
		log.Println("Unable to read payload as JSON")
		log.Println(err)
		return
	}

	repo := dockerHubPayload.Repository.RepoName
	command, ok := repoCommands[repo]

	if !ok { // || len(command) == 0 {
		log.Printf("Repository \"%s\" not enabled\n", repo)
		return
	}

	log.Println("Processing", repo)
	log.Println("Running", command)

	repoCmd := exec.Command(command[0], command[1:]...)

	output, err := repoCmd.Output()
	if err != nil {
		panic(err)
	}

	log.Println(string(output))

}

func main() {

	// Accept all environment variables starting with AUTODOCK_ as configuration
	// for autodock. We're doing this instead of using flags because of how the
	// google/golang-runtime image works (no command line arguments).
	for _, e := range os.Environ() {
		pair := strings.Split(e, "=")
		key := pair[0]
		if strings.Contains(key, "AUTODOCK_") {
			autodockit := os.Getenv(key)
			autodocksplit := strings.Split(autodockit, ":")

			repo := autodocksplit[0]
			commands := strings.Join(autodocksplit[1:], ":")

			// Lazy mode, accepting spaces as delimiters between command arguments
			repoCommands[repo] = strings.Split(commands, " ")

		}
	}

	if len(repoCommands) == 0 {
		panic("No repositories configured")
	}

	log.Println("Docker repository actions:")
	for repo, commands := range repoCommands {
		log.Printf("\t%s: %s\n", repo, commands)
	}

	// TODO: Print out the full URL for the webhook on registry.hub.docker.com
	// TODO: Determine IP of the public host?
	log.Println("Point your Hook config at: http://{IP+Port}/autodock/v1/")

	http.HandleFunc("/autodock/v1/", DockerHubHandler)
	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"sendgrid-activities/api"
)

func main() {
	const required = "REQUIRED"

	apiUser := flag.String("username", required, "Username to connect to the SendGrid API")
	apiKey := flag.String("password", required, "Password to connect to the SendGrid API")
	flag.Parse()

	if *apiUser == required || *apiKey == required {
		fmt.Println("Username and password are required.")
		return
	}

	sg := api.NewSendGridClient(*apiUser, *apiKey)

	bounces, err := sg.GetBounces()
	if err != nil {
		fmt.Println("The response of the Bounces API doesn't match the expected format.\nThis can happen if you have entered the wrong credentials.")
	} else {
		printActivities(bounces, "bounce")
	}

	blocks, err := sg.GetBlocks()
	if err != nil {
		fmt.Println("The response of the Blocks API doesn't match the expected format.\nThis can happen if you have entered the wrong credentials.")
	} else {
		printActivities(blocks, "blocks")
	}

	invalidEmails, err := sg.GetInvalidEmails()
	if err != nil {
		fmt.Println("The response of the InvalidEmails API doesn't match the expected format.\nThis can happen if you have entered the wrong credentials.")
	} else {
		printActivities(invalidEmails, "invalid-emails")
	}
}

func printActivities(activities []*api.Activity, activityType string) {
	if len(activities) == 0 {
		return
	}

	for _, activity := range activities {
		fmt.Printf("\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", activityType, activity.Created, activity.Status, activity.Email, activity.Reason)
	}
}
<commit_msg>Add type flag to filter on activity type<commit_after>package main

import (
	"flag"
	"fmt"
	"sendgrid-activities/api"
	"strings"
)

const (
	all           = "all"
	bounces       = "bounces"
	blocks        = "blocks"
	invalidEmails = "invalidEmails"
)

func main() {
	const required = "REQUIRED"

	apiUser := flag.String("username", required, "Username to connect to the SendGrid API")
	apiKey := flag.String("password", required, "Password to connect to the SendGrid API")
	activityType := flag.String("type", "all", "Types of activities to retrieve (all, bounces, blocks, invalidEmails)")
	flag.Parse()

	if *apiUser == required || *apiKey == required {
		fmt.Println("Username and password are required")
		return
	}

	sg := api.NewSendGridClient(*apiUser, *apiKey)

	switch strings.ToLower(*activityType) {
	case all:
		printAll(sg)
	case bounces:
		activities, err := sg.GetBounces()
		printActivities(activities, err)
	case blocks:
		activities, err := sg.GetBlocks()
		printActivities(activities, err)
	case strings.ToLower(invalidEmails):
		activities, err := sg.GetInvalidEmails()
		printActivities(activities, err)
	default:
		fmt.Printf("Invalid activity type: %s\n", *activityType)
	}

}

func printAll(sg *api.SGClient) {
	var activities []*api.Activity
	bouncesActivities, err := sg.GetBounces()
	if err == nil {
		activities = append(activities, bouncesActivities...)
	} else {
		printError(err)
	}

	blocksActivities, err := sg.GetBlocks()
	if err == nil {
		activities = append(activities, blocksActivities...)
	} else {
		printError(err)
	}

	invalidEmailsActivities, err := sg.GetInvalidEmails()
	if err == nil {
		activities = append(activities, invalidEmailsActivities...)
	} else {
		printError(err)
	}

	printActivities(activities, err)
}

func printActivities(activities []*api.Activity, err error) {
	if err != nil {
		printError(err)
	}

	if len(activities) > 0 {
		fmt.Printf("\"Created\",\"Status\",\"Email\",\"Reason\"\n")
	}

	for _, activity := range activities {
		fmt.Printf("\"%s\",\"%s\",\"%s\",\"%s\"\n", activity.Created, activity.Status, activity.Email, activity.Reason)
	}
}

func printError(err error) {
	fmt.Printf("Error whilst retrieving activities: %s\n", err)
	fmt.Printf("This usually happens if you have entered the wrong credentials.\n")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/fogleman/primitive/primitive"
	"github.com/nfnt/resize"
)

var (
	Input      string
	Output     string
	Background string
	Number     int
	Alpha      int
	InputSize  int
	OutputSize int
	Mode       int
	Workers    int
	V, VV      bool
)

func init() {
	flag.StringVar(&Input, "i", "", "input image path")
	flag.StringVar(&Output, "o", "", "output image path")
	flag.StringVar(&Background, "bg", "", "background color (hex)")
	flag.IntVar(&Number, "n", 0, "number of primitives")
	flag.IntVar(&Alpha, "a", 128, "alpha value")
	flag.IntVar(&InputSize, "r", 256, "resize large input images to this size")
	flag.IntVar(&OutputSize, "s", 1024, "output image size")
	flag.IntVar(&Mode, "m", 1, "0=combo 1=triangle 2=rect 3=ellipse 4=circle 5=rotatedrect")
	flag.IntVar(&Workers, "j", 0, "number of parallel workers (default uses all cores)")
	flag.BoolVar(&V, "v", false, "verbose")
	flag.BoolVar(&VV, "vv", false, "very verbose")
}

func errorMessage(message string) bool {
	fmt.Fprintln(os.Stderr, message)
	return false
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	// parse and validate arguments
	flag.Parse()
	ok := true
	if Input == "" {
		ok = errorMessage("ERROR: input argument required")
	}
	if Output == "" {
		ok = errorMessage("ERROR: output argument required")
	}
	if Number == 0 {
		ok = errorMessage("ERROR: number argument required")
	}
	if !ok {
		fmt.Println("Usage: primitive [OPTIONS] -i input -o output -n shape_count")
		flag.PrintDefaults()
		os.Exit(1)
	}

	// set log level
	if V {
		primitive.LogLevel = 1
	}
	if VV {
		primitive.LogLevel = 2
	}

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

	// read input image
	primitive.Log(1, "reading %s\n", Input)
	input, err := primitive.LoadImage(Input)
	check(err)

	// scale down input image if needed
	size := uint(InputSize)
	input = resize.Thumbnail(size, size, input, resize.Bilinear)

	// determine output options
	ext := strings.ToLower(filepath.Ext(Output))
	saveFrames := strings.Contains(Output, "%") && ext != ".gif"

	// determine background color
	var bg primitive.Color
	if Background == "" {
		bg = primitive.MakeColor(primitive.AverageImageColor(input))
	} else {
		bg = primitive.MakeHexColor(Background)
	}

	// run algorithm
	model := primitive.NewModel(input, bg, OutputSize)
	start := time.Now()
	for i := 1; i <= Number; i++ {
		// find optimal shape and add it to the model
		model.Step(primitive.ShapeType(Mode), Alpha, Workers)
		elapsed := time.Since(start).Seconds()
		primitive.Log(1, "iteration %d, time %.3f, score %.6f\n", i, elapsed, model.Score)

		// write output image(s)
		if saveFrames || i == Number {
			path := Output
			if saveFrames {
				path = fmt.Sprintf(Output, i)
			}
			primitive.Log(1, "writing %s\n", path)
			switch ext {
			default:
				check(fmt.Errorf("unrecognized file extension: %s", ext))
			case ".png":
				check(primitive.SavePNG(path, model.Context.Image()))
			case ".jpg", ".jpeg":
				check(primitive.SaveJPG(path, model.Context.Image(), 95))
			case ".svg":
				check(primitive.SaveFile(path, model.SVG()))
			case ".gif":
				frames := model.Frames(0.001)
				check(primitive.SaveGIFImageMagick(path, frames, 50, 250))
			}
		}
	}
}
<commit_msg>support multiple outputs, close #15<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/fogleman/primitive/primitive"
	"github.com/nfnt/resize"
)

var (
	Input      string
	Outputs    flagArray
	Background string
	Number     int
	Alpha      int
	InputSize  int
	OutputSize int
	Mode       int
	Workers    int
	V, VV      bool
)

type flagArray []string

func (i *flagArray) String() string {
	return strings.Join(*i, ", ")
}

func (i *flagArray) Set(value string) error {
	*i = append(*i, value)
	return nil
}

func init() {
	flag.StringVar(&Input, "i", "", "input image path")
	flag.Var(&Outputs, "o", "output image path")
	flag.StringVar(&Background, "bg", "", "background color (hex)")
	flag.IntVar(&Number, "n", 0, "number of primitives")
	flag.IntVar(&Alpha, "a", 128, "alpha value")
	flag.IntVar(&InputSize, "r", 256, "resize large input images to this size")
	flag.IntVar(&OutputSize, "s", 1024, "output image size")
	flag.IntVar(&Mode, "m", 1, "0=combo 1=triangle 2=rect 3=ellipse 4=circle 5=rotatedrect")
	flag.IntVar(&Workers, "j", 0, "number of parallel workers (default uses all cores)")
	flag.BoolVar(&V, "v", false, "verbose")
	flag.BoolVar(&VV, "vv", false, "very verbose")
}

func errorMessage(message string) bool {
	fmt.Fprintln(os.Stderr, message)
	return false
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	// parse and validate arguments
	flag.Parse()
	ok := true
	if Input == "" {
		ok = errorMessage("ERROR: input argument required")
	}
	if len(Outputs) == 0 {
		ok = errorMessage("ERROR: output argument required")
	}
	if Number == 0 {
		ok = errorMessage("ERROR: number argument required")
	}
	if !ok {
		fmt.Println("Usage: primitive [OPTIONS] -i input -o output -n shape_count")
		flag.PrintDefaults()
		os.Exit(1)
	}

	// set log level
	if V {
		primitive.LogLevel = 1
	}
	if VV {
		primitive.LogLevel = 2
	}

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

	// read input image
	primitive.Log(1, "reading %s\n", Input)
	input, err := primitive.LoadImage(Input)
	check(err)

	// scale down input image if needed
	size := uint(InputSize)
	input = resize.Thumbnail(size, size, input, resize.Bilinear)

	// determine background color
	var bg primitive.Color
	if Background == "" {
		bg = primitive.MakeColor(primitive.AverageImageColor(input))
	} else {
		bg = primitive.MakeHexColor(Background)
	}

	// run algorithm
	model := primitive.NewModel(input, bg, OutputSize)
	start := time.Now()
	for i := 1; i <= Number; i++ {
		// find optimal shape and add it to the model
		model.Step(primitive.ShapeType(Mode), Alpha, Workers)
		elapsed := time.Since(start).Seconds()
		primitive.Log(1, "iteration %d, time %.3f, score %.6f\n", i, elapsed, model.Score)

		// write output image(s)
		for _, output := range Outputs {
			ext := strings.ToLower(filepath.Ext(output))
			saveFrames := strings.Contains(output, "%") && ext != ".gif"
			if saveFrames || i == Number {
				path := output
				if saveFrames {
					path = fmt.Sprintf(output, i)
				}
				primitive.Log(1, "writing %s\n", path)
				switch ext {
				default:
					check(fmt.Errorf("unrecognized file extension: %s", ext))
				case ".png":
					check(primitive.SavePNG(path, model.Context.Image()))
				case ".jpg", ".jpeg":
					check(primitive.SaveJPG(path, model.Context.Image(), 95))
				case ".svg":
					check(primitive.SaveFile(path, model.SVG()))
				case ".gif":
					frames := model.Frames(0.001)
					check(primitive.SaveGIFImageMagick(path, frames, 50, 250))
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/julienschmidt/httprouter"
	"net/http"
	"log"
	"os"
	"fmt"
	"database/sql"
	_ "github.com/lib/pq"
)

var conn *sql.DB

type BlogPost {
	Id int64
	Titel string
	Text string
	Auteur string
	Img_url string
	Ctime string
	Image string
}

func GetBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM blog")
	data := []BlogPost{}
	for rows.Next() {
		post := BlogPost{}
		rows.Scan(&post.Id, &post.Titel, &post.Text, &post.Auteur, &post.Img_url, &post.Ctime, &post.Image)
		data = append(data, post)
	}
	buf,_ := json.Marshal(data)
	w.Write(buf)
}

func GetSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func GetServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func PostBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func PostSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func PostServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func main() {
	conn,_ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
	defer conn.Close()
	router := httprouter.New()
	router.GET("/blog", GetBlog)
	router.GET("/spin", GetSpinData)
	router.GET("/servo", GetServoData)
	router.POST("/blog", PostBlog)
	router.POST("/spin", PostSpinData)
	router.POST("/servo", PostServoData)
	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	fmt.Printf("Starting server at localhost:%s...", port)
	log.Fatal(http.ListenAndServe(":"+port, router))
}<commit_msg>fixed oversight<commit_after>package main

import (
	"encoding/json"
	"github.com/julienschmidt/httprouter"
	"net/http"
	"log"
	"os"
	"fmt"
	"database/sql"
	_ "github.com/lib/pq"
)

var conn *sql.DB

type BlogPost struct {
	Id int64
	Titel string
	Text string
	Auteur string
	Img_url string
	Ctime string
	Image string
}

func GetBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	rows,_ := conn.Query("SELECT * FROM blog")
	data := []BlogPost{}
	for rows.Next() {
		post := BlogPost{}
		rows.Scan(&post.Id, &post.Titel, &post.Text, &post.Auteur, &post.Img_url, &post.Ctime, &post.Image)
		data = append(data, post)
	}
	buf,_ := json.Marshal(data)
	w.Write(buf)
}

func GetSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func GetServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func PostBlog(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func PostSpinData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func PostServoData(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	data,_ := json.Marshal("blah")
	w.Write(data)
}

func main() {
	conn,_ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
	defer conn.Close()
	router := httprouter.New()
	router.GET("/blog", GetBlog)
	router.GET("/spin", GetSpinData)
	router.GET("/servo", GetServoData)
	router.POST("/blog", PostBlog)
	router.POST("/spin", PostSpinData)
	router.POST("/servo", PostServoData)
	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	fmt.Printf("Starting server at localhost:%s...", port)
	log.Fatal(http.ListenAndServe(":"+port, router))
}<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/evolsnow/robot/conn"
	"golang.org/x/net/websocket"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func main() {
	var configFile string
	var debug bool

	flag.StringVar(&configFile, "c", "config.json", "specify config file")
	flag.BoolVar(&debug, "d", false, "debug mode")
	flag.Parse()
	config, err := ParseConfig(configFile)
	if err != nil {
		log.Fatal("a vailid json config file must exist")
	}

	//connect to redis
	redisPort := strconv.Itoa(config.RedisPort)
	redisServer := net.JoinHostPort(config.RedisAddress, redisPort)
	if !conn.Ping(redisServer, config.RedisPassword) {
		log.Fatal("connect to redis server failed")
	}
	conn.Pool = conn.NewPool(redisServer, config.RedisPassword, config.RedisDB)

	//create robot and run
	robot := newRobot(config.RobotToken, config.RobotName, config.WebHookUrl)
	robot.bot.Debug = debug
	go robot.run()

	go groupTalk()

	//run server and web samaritan
	srvPort := strconv.Itoa(config.Port)
	http.HandleFunc("/ajax", ajax)
	http.Handle("/websocket", websocket.Handler(socketHandler))
	log.Fatal(http.ListenAndServeTLS(net.JoinHostPort(config.Server, srvPort), config.Cert, config.CertKey, nil))

}

func groupTalk() {
	tlChan := make(chan string)
	qinChan := make(chan string)
	//iceChan := make(chan string, 5)
	initSentence := "你好"
	//iceChan <- tlAI(initSentence)
	go func() {
		qinChan <- tlAI(initSentence)
	}()
	for {
		select {
		//case msgToIce := <-iceChan:
		//	replyFromIce := iceAI(msgToIce)
		//	tlChan <- replyFromIce
		//	qinChan <- replyFromIce
		case msgToTl := <-tlChan:
			replyFromTl := tlAI(msgToTl)
			qinChan <- replyFromTl
		//iceChan <- replyFromTl
		case msgToQin := <-qinChan:
			replyFromQin := qinAI(msgToQin)
			//iceChan <- replyFromQin
			tlChan <- replyFromQin
		}
	}
}

//used for web samaritan robot
func socketHandler(ws *websocket.Conn) {
	for {
		var in string
		var ret []string
		if err := websocket.Message.Receive(ws, &in); err != nil {
			log.Println("socket closed")
			return
		}
		ret = receive(in)

		for i := range ret {
			websocket.Message.Send(ws, ret[i])
			time.Sleep(time.Second)
		}
		websocket.Message.Send(ws, "")
	}
}

//when webSocket unavailable, fallback to ajax long polling
func ajax(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	var messages = make(chan string)
	if r.Method == "GET" {
		w.Write([]byte(<-messages))
	} else {
		body := r.FormValue("text")
		if body != "" {
			go func(string) {
				ret := receive(body)
				for i := range ret {
					messages <- ret[i]
					time.Sleep(time.Second)
				}
				messages <- ""
			}(body)
		}
	}
}

//receive from client
func receive(in string) (ret []string) {
	defer func() {
		if p := recover(); p != nil {
			err := fmt.Errorf("client closed error: %v", p)
			log.Println(err)
		}
	}()
	fmt.Printf("Received: %s\n", in)
	var response string
	var answer = make(chan string)
	sf := func(c rune) bool {
		return c == ',' || c == '，' || c == ';' || c == '。' || c == '.' || c == '？' || c == '?'
	}
	if chinese(in) {
		go func() {
			answer <- iceAI(in)
		}()
		go func() {
			answer <- tlAI(in)
		}()
		go func() {
			ret := qinAI(in)
			if ret != "" {
				answer <- strings.Replace(ret, "Jarvis", "samaritan", -1)
			}
		}()
		response = <-answer
		// Separate into fields with func.
		ret = strings.FieldsFunc(response, sf)

	} else {
		response = mitAI(in)
		ret = strings.FieldsFunc(response, sf)
	}
	return
}
<commit_msg>test qinai<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/evolsnow/robot/conn"
	"golang.org/x/net/websocket"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func main() {
	var configFile string
	var debug bool

	flag.StringVar(&configFile, "c", "config.json", "specify config file")
	flag.BoolVar(&debug, "d", false, "debug mode")
	flag.Parse()
	config, err := ParseConfig(configFile)
	if err != nil {
		log.Fatal("a vailid json config file must exist")
	}

	//connect to redis
	redisPort := strconv.Itoa(config.RedisPort)
	redisServer := net.JoinHostPort(config.RedisAddress, redisPort)
	if !conn.Ping(redisServer, config.RedisPassword) {
		log.Fatal("connect to redis server failed")
	}
	conn.Pool = conn.NewPool(redisServer, config.RedisPassword, config.RedisDB)

	//create robot and run
	robot := newRobot(config.RobotToken, config.RobotName, config.WebHookUrl)
	robot.bot.Debug = debug
	go robot.run()

	go groupTalk()

	//run server and web samaritan
	srvPort := strconv.Itoa(config.Port)
	http.HandleFunc("/ajax", ajax)
	http.Handle("/websocket", websocket.Handler(socketHandler))
	log.Fatal(http.ListenAndServeTLS(net.JoinHostPort(config.Server, srvPort), config.Cert, config.CertKey, nil))

}

func groupTalk() {
	tlChan := make(chan string)
	qinChan := make(chan string)
	//iceChan := make(chan string, 5)
	initSentence := "你好"
	//iceChan <- tlAI(initSentence)
	go func() {
		qinChan <- tlAI(initSentence)
	}()
	for {
		select {
		//case msgToIce := <-iceChan:
		//	replyFromIce := iceAI(msgToIce)
		//	tlChan <- replyFromIce
		//	qinChan <- replyFromIce
		case msgToTl := <-tlChan:
			replyFromTl := tlAI(msgToTl)
			qinChan <- replyFromTl
		//iceChan <- replyFromTl
		case <-qinChan:
			replyFromQin := qinAI("你好")
			//iceChan <- replyFromQin
			tlChan <- replyFromQin
		}
	}
}

//used for web samaritan robot
func socketHandler(ws *websocket.Conn) {
	for {
		var in string
		var ret []string
		if err := websocket.Message.Receive(ws, &in); err != nil {
			log.Println("socket closed")
			return
		}
		ret = receive(in)

		for i := range ret {
			websocket.Message.Send(ws, ret[i])
			time.Sleep(time.Second)
		}
		websocket.Message.Send(ws, "")
	}
}

//when webSocket unavailable, fallback to ajax long polling
func ajax(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "*")
	var messages = make(chan string)
	if r.Method == "GET" {
		w.Write([]byte(<-messages))
	} else {
		body := r.FormValue("text")
		if body != "" {
			go func(string) {
				ret := receive(body)
				for i := range ret {
					messages <- ret[i]
					time.Sleep(time.Second)
				}
				messages <- ""
			}(body)
		}
	}
}

//receive from client
func receive(in string) (ret []string) {
	defer func() {
		if p := recover(); p != nil {
			err := fmt.Errorf("client closed error: %v", p)
			log.Println(err)
		}
	}()
	fmt.Printf("Received: %s\n", in)
	var response string
	var answer = make(chan string)
	sf := func(c rune) bool {
		return c == ',' || c == '，' || c == ';' || c == '。' || c == '.' || c == '？' || c == '?'
	}
	if chinese(in) {
		go func() {
			answer <- iceAI(in)
		}()
		go func() {
			answer <- tlAI(in)
		}()
		go func() {
			ret := qinAI(in)
			if ret != "" {
				answer <- strings.Replace(ret, "Jarvis", "samaritan", -1)
			}
		}()
		response = <-answer
		// Separate into fields with func.
		ret = strings.FieldsFunc(response, sf)

	} else {
		response = mitAI(in)
		ret = strings.FieldsFunc(response, sf)
	}
	return
}
<|endoftext|>