<commit_before>// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).

package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"github.com/golang/groupcache/lru"
	"github.com/juju/ratelimit"
	"github.com/kardianos/osext"

	"github.com/syncthing/relaysrv/client"
	"github.com/syncthing/syncthing/lib/sync"
	"github.com/syncthing/syncthing/lib/tlsutil"
)

type relay struct {
	URL string `json:"url"`
	uri *url.URL
}

func (r relay) String() string {
	return r.URL
}

type request struct {
	relay  relay
	uri    *url.URL
	result chan result
}

type result struct {
	err      error
	eviction time.Duration
}

var (
	binDir         string
	testCert       []tls.Certificate
	listen         string        = ":80"
	dir            string        = ""
	evictionTime   time.Duration = time.Hour
	debug          bool          = false
	getLRUSize     int           = 10240
	getLimit       time.Duration
	getLimitBurst  int64 = 10
	postLRUSize    int   = 128
	postLimit      time.Duration
	postLimitBurst int64 = 2

	getMut      sync.RWMutex = sync.NewRWMutex()
	getLRUCache *lru.Cache

	postMut      sync.RWMutex = sync.NewRWMutex()
	postLRUCache *lru.Cache

	requests = make(chan request, 10)

	mut             sync.RWMutex           = sync.NewRWMutex()
	knownRelays     []relay                = make([]relay, 0)
	permanentRelays []relay                = make([]relay, 0)
	evictionTimers  map[string]*time.Timer = make(map[string]*time.Timer)
)

func main() {
	var getLimitAvg, postLimitAvg int

	flag.StringVar(&listen, "listen", listen, "Listen address")
	flag.StringVar(&dir, "keys", dir, "Directory where http-cert.pem and http-key.pem is stored for TLS listening")
	flag.BoolVar(&debug, "debug", debug, "Enable debug output")
	flag.DurationVar(&evictionTime, "eviction", evictionTime, "After how long the relay is evicted")
	flag.IntVar(&getLRUSize, "get-limit-cache", getLRUSize, "Get request limiter cache size")
	flag.IntVar(&getLimitAvg, "get-limit-avg", 2, "Allowed average get request rate, per 10 s")
	flag.Int64Var(&getLimitBurst, "get-limit-burst", getLimitBurst, "Allowed burst get requests")
	flag.IntVar(&postLRUSize, "post-limit-cache", postLRUSize, "Post request limiter cache size")
	flag.IntVar(&postLimitAvg, "post-limit-avg", 2, "Allowed average post request rate, per minute")
	flag.Int64Var(&postLimitBurst, "post-limit-burst", postLimitBurst, "Allowed burst post requests")

	flag.Parse()

	getLimit = 10 * time.Second / time.Duration(getLimitAvg)
	postLimit = time.Minute / time.Duration(postLimitAvg)

	getLRUCache = lru.New(getLRUSize)
	postLRUCache = lru.New(postLRUSize)

	var listener net.Listener
	var err error

	binDir, err = osext.ExecutableFolder()
	if err != nil {
		log.Fatalln("Failed to locate executable directory")
	}

	loadPermanentRelays()
	loadOrCreateTestCertificate()
	go requestProcessor()

	if dir != "" {
		if debug {
			log.Println("Starting TLS listener on", listen)
		}
		certFile, keyFile := filepath.Join(dir, "http-cert.pem"), filepath.Join(dir, "http-key.pem")
		cert, err := tls.LoadX509KeyPair(certFile, keyFile)
		if err != nil {
			log.Fatalln("Failed to load HTTP X509 key pair:", err)
		}

		tlsCfg := &tls.Config{
			Certificates: []tls.Certificate{cert},
			MinVersion:   tls.VersionTLS10, // No SSLv3
			CipherSuites: []uint16{
				// No RC4
				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
				tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
				tls.TLS_RSA_WITH_AES_128_CBC_SHA,
				tls.TLS_RSA_WITH_AES_256_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
				tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
			},
		}

		listener, err = tls.Listen("tcp", listen, tlsCfg)
	} else {
		if debug {
			log.Println("Starting plain listener on", listen)
		}
		listener, err = net.Listen("tcp", listen)
	}

	if err != nil {
		log.Fatalln("listen:", err)
	}

	handler := http.NewServeMux()
	handler.HandleFunc("/", handleRequest)

	srv := http.Server{
		Handler:     handler,
		ReadTimeout: 10 * time.Second,
	}

	err = srv.Serve(listener)
	if err != nil {
		log.Fatalln("serve:", err)
	}
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		if limit(r.RemoteAddr, getLRUCache, getMut, getLimit, int64(getLimitBurst)) {
			w.WriteHeader(429)
			return
		}
		handleGetRequest(w, r)
	case "POST":
		if limit(r.RemoteAddr, postLRUCache, postMut, postLimit, int64(postLimitBurst)) {
			w.WriteHeader(429)
			return
		}
		handlePostRequest(w, r)
	default:
		if debug {
			log.Println("Unhandled HTTP method", r.Method)
		}
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
	}
}

func handleGetRequest(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	mut.RLock()
	relays := append(permanentRelays, knownRelays...)
	mut.RUnlock()

	// Shuffle
	for i := range relays {
		j := rand.Intn(i + 1)
		relays[i], relays[j] = relays[j], relays[i]
	}

	json.NewEncoder(w).Encode(map[string][]relay{
		"relays": relays,
	})
}

func handlePostRequest(w http.ResponseWriter, r *http.Request) {
	var newRelay relay
	err := json.NewDecoder(r.Body).Decode(&newRelay)
	r.Body.Close()

	if err != nil {
		if debug {
			log.Println("Failed to parse payload")
		}
		http.Error(w, err.Error(), 500)
		return
	}

	uri, err := url.Parse(newRelay.URL)
	if err != nil {
		if debug {
			log.Println("Failed to parse URI", newRelay.URL)
		}
		http.Error(w, err.Error(), 500)
		return
	}

	host, port, err := net.SplitHostPort(uri.Host)
	if err != nil {
		if debug {
			log.Println("Failed to split URI", newRelay.URL)
		}
		http.Error(w, err.Error(), 500)
		return
	}

	// Get the IP address of the client
	rhost, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		if debug {
			log.Println("Failed to split remote address", r.RemoteAddr)
		}
		http.Error(w, err.Error(), 500)
		return
	}

	// The client did not provide an IP address, use the IP address of the client.
	if host == "" {
		uri.Host = net.JoinHostPort(rhost, port)
		newRelay.URL = uri.String()
	} else if host != rhost {
		if debug {
			log.Println("IP address advertised does not match client IP address", r.RemoteAddr, uri)
		}
		http.Error(w, "IP address does not match client IP", http.StatusUnauthorized)
		return
	}
	newRelay.uri = uri

	for _, current := range permanentRelays {
		if current.uri.Host == newRelay.uri.Host {
			if debug {
				log.Println("Asked to add a relay", newRelay, "which exists in permanent list")
			}
			http.Error(w, "Invalid request", 500)
			return
		}
	}

	reschan := make(chan result)

	select {
	case requests <- request{newRelay, uri, reschan}:
		result := <-reschan
		if result.err != nil {
			http.Error(w, result.err.Error(), 500)
			return
		}
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(map[string]time.Duration{
			"evictionIn": result.eviction,
		})

	default:
		if debug {
			log.Println("Dropping request")
		}
		w.WriteHeader(429)
	}
}

func requestProcessor() {
	for request := range requests {
		if debug {
			log.Println("Request for", request.relay)
		}
		if !client.TestRelay(request.uri, testCert, 250*time.Millisecond, 4) {
			if debug {
				log.Println("Test for relay", request.relay, "failed")
			}
			request.result <- result{fmt.Errorf("test failed"), 0}
			continue
		}

		mut.Lock()
		timer, ok := evictionTimers[request.relay.uri.Host]
		if ok {
			if debug {
				log.Println("Stopping existing timer for", request.relay)
			}
			timer.Stop()
		}

		for _, current := range knownRelays {
			if current.uri.Host == request.relay.uri.Host {
				if debug {
					log.Println("Relay", request.relay, "already exists")
				}
				goto found
			}
		}

		if debug {
			log.Println("Adding new relay", request.relay)
		}
		knownRelays = append(knownRelays, request.relay)

	found:
		evictionTimers[request.relay.uri.Host] = time.AfterFunc(evictionTime, evict(request.relay))
		mut.Unlock()
		request.result <- result{nil, evictionTime}
	}

}

func evict(relay relay) func() {
	return func() {
		mut.Lock()
		defer mut.Unlock()
		if debug {
			log.Println("Evicting", relay)
		}
		for i, current := range knownRelays {
			if current.uri.Host == relay.uri.Host {
				if debug {
					log.Println("Evicted", relay)
				}
				last := len(knownRelays) - 1
				knownRelays[i] = knownRelays[last]
				knownRelays = knownRelays[:last]
			}
		}
		delete(evictionTimers, relay.uri.Host)
	}
}

func limit(addr string, cache *lru.Cache, lock sync.RWMutex, rate time.Duration, burst int64) bool {
	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return false
	}

	lock.RLock()
	bkt, ok := cache.Get(host)
	lock.RUnlock()
	if ok {
		bkt := bkt.(*ratelimit.Bucket)
		if bkt.TakeAvailable(1) != 1 {
			// Rate limit
			return true
		}
	} else {
		lock.Lock()
		cache.Add(host, ratelimit.NewBucket(rate, burst))
		lock.Unlock()
	}
	return false
}

func loadPermanentRelays() {
	path, err := osext.ExecutableFolder()
	if err != nil {
		log.Println("Failed to locate executable directory")
		return
	}

	content, err := ioutil.ReadFile(filepath.Join(path, "relays"))
	if err != nil {
		return
	}

	for _, line := range strings.Split(string(content), "\n") {
		if len(line) == 0 {
			continue
		}

		uri, err := url.Parse(line)
		if err != nil {
			if debug {
				log.Println("Skipping permanent relay", line, "due to parse error", err)
			}
			continue
		}

		permanentRelays = append(permanentRelays, relay{
			URL: line,
			uri: uri,
		})
		if debug {
			log.Println("Adding permanent relay", line)
		}
	}
}

func loadOrCreateTestCertificate() {
	certFile, keyFile := filepath.Join(binDir, "cert.pem"), filepath.Join(binDir, "key.pem")
	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err == nil {
		testCert = []tls.Certificate{cert}
		return
	}

	cert, err = tlsutil.NewCertificate(certFile, keyFile, "relaypoolsrv", 3072)
	if err != nil {
		log.Fatalln("Failed to create test X509 key pair:", err)
	}
	testCert = []tls.Certificate{cert}
}
<commit_msg>Default values tweak<commit_after>// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).

package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"github.com/golang/groupcache/lru"
	"github.com/juju/ratelimit"
	"github.com/kardianos/osext"

	"github.com/syncthing/relaysrv/client"
	"github.com/syncthing/syncthing/lib/sync"
	"github.com/syncthing/syncthing/lib/tlsutil"
)

type relay struct {
	URL string `json:"url"`
	uri *url.URL
}

func (r relay) String() string {
	return r.URL
}

type request struct {
	relay  relay
	uri    *url.URL
	result chan result
}

type result struct {
	err      error
	eviction time.Duration
}

var (
	binDir         string
	testCert       []tls.Certificate
	listen         string        = ":80"
	dir            string        = ""
	evictionTime   time.Duration = time.Hour
	debug          bool          = false
	getLRUSize     int           = 10 << 10
	getLimitBurst  int64         = 10
	getLimitAvg                  = 1
	postLRUSize    int           = 1 << 10
	postLimitBurst int64         = 2
	postLimitAvg                 = 1
	getLimit       time.Duration
	postLimit      time.Duration

	getMut      sync.RWMutex = sync.NewRWMutex()
	getLRUCache *lru.Cache

	postMut      sync.RWMutex = sync.NewRWMutex()
	postLRUCache *lru.Cache

	requests = make(chan request, 10)

	mut             sync.RWMutex           = sync.NewRWMutex()
	knownRelays     []relay                = make([]relay, 0)
	permanentRelays []relay                = make([]relay, 0)
	evictionTimers  map[string]*time.Timer = make(map[string]*time.Timer)
)

func main() {
	flag.StringVar(&listen, "listen", listen, "Listen address")
	flag.StringVar(&dir, "keys", dir, "Directory where http-cert.pem and http-key.pem is stored for TLS listening")
	flag.BoolVar(&debug, "debug", debug, "Enable debug output")
	flag.DurationVar(&evictionTime, "eviction", evictionTime, "After how long the relay is evicted")
	flag.IntVar(&getLRUSize, "get-limit-cache", getLRUSize, "Get request limiter cache size")
	flag.IntVar(&getLimitAvg, "get-limit-avg", 2, "Allowed average get request rate, per 10 s")
	flag.Int64Var(&getLimitBurst, "get-limit-burst", getLimitBurst, "Allowed burst get requests")
	flag.IntVar(&postLRUSize, "post-limit-cache", postLRUSize, "Post request limiter cache size")
	flag.IntVar(&postLimitAvg, "post-limit-avg", 2, "Allowed average post request rate, per minute")
	flag.Int64Var(&postLimitBurst, "post-limit-burst", postLimitBurst, "Allowed burst post requests")

	flag.Parse()

	getLimit = 10 * time.Second / time.Duration(getLimitAvg)
	postLimit = time.Minute / time.Duration(postLimitAvg)

	getLRUCache = lru.New(getLRUSize)
	postLRUCache = lru.New(postLRUSize)

	var listener net.Listener
	var err error

	binDir, err = osext.ExecutableFolder()
	if err != nil {
		log.Fatalln("Failed to locate executable directory")
	}

	loadPermanentRelays()
	loadOrCreateTestCertificate()
	go requestProcessor()

	if dir != "" {
		if debug {
			log.Println("Starting TLS listener on", listen)
		}
		certFile, keyFile := filepath.Join(dir, "http-cert.pem"), filepath.Join(dir, "http-key.pem")
		cert, err := tls.LoadX509KeyPair(certFile, keyFile)
		if err != nil {
			log.Fatalln("Failed to load HTTP X509 key pair:", err)
		}

		tlsCfg := &tls.Config{
			Certificates: []tls.Certificate{cert},
			MinVersion:   tls.VersionTLS10, // No SSLv3
			CipherSuites: []uint16{
				// No RC4
				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
				tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
				tls.TLS_RSA_WITH_AES_128_CBC_SHA,
				tls.TLS_RSA_WITH_AES_256_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
				tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
			},
		}

		listener, err = tls.Listen("tcp", listen, tlsCfg)
	} else {
		if debug {
			log.Println("Starting plain listener on", listen)
		}
		listener, err = net.Listen("tcp", listen)
	}

	if err != nil {
		log.Fatalln("listen:", err)
	}

	handler := http.NewServeMux()
	handler.HandleFunc("/", handleRequest)

	srv := http.Server{
		Handler:     handler,
		ReadTimeout: 10 * time.Second,
	}

	err = srv.Serve(listener)
	if err != nil {
		log.Fatalln("serve:", err)
	}
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		if limit(r.RemoteAddr, getLRUCache, getMut, getLimit, int64(getLimitBurst)) {
			w.WriteHeader(429)
			return
		}
		handleGetRequest(w, r)
	case "POST":
		if limit(r.RemoteAddr, postLRUCache, postMut, postLimit, int64(postLimitBurst)) {
			w.WriteHeader(429)
			return
		}
		handlePostRequest(w, r)
	default:
		if debug {
			log.Println("Unhandled HTTP method", r.Method)
		}
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
	}
}

func handleGetRequest(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	mut.RLock()
	relays := append(permanentRelays, knownRelays...)
	mut.RUnlock()

	// Shuffle
	for i := range relays {
		j := rand.Intn(i + 1)
		relays[i], relays[j] = relays[j], relays[i]
	}

	json.NewEncoder(w).Encode(map[string][]relay{
		"relays": relays,
	})
}

func handlePostRequest(w http.ResponseWriter, r *http.Request) {
	var newRelay relay
	err := json.NewDecoder(r.Body).Decode(&newRelay)
	r.Body.Close()

	if err != nil {
		if debug {
			log.Println("Failed to parse payload")
		}
		http.Error(w, err.Error(), 500)
		return
	}

	uri, err := url.Parse(newRelay.URL)
	if err != nil {
		if debug {
			log.Println("Failed to parse URI", newRelay.URL)
		}
		http.Error(w, err.Error(), 500)
		return
	}

	host, port, err := net.SplitHostPort(uri.Host)
	if err != nil {
		if debug {
			log.Println("Failed to split URI", newRelay.URL)
		}
		http.Error(w, err.Error(), 500)
		return
	}

	// Get the IP address of the client
	rhost, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		if debug {
			log.Println("Failed to split remote address", r.RemoteAddr)
		}
		http.Error(w, err.Error(), 500)
		return
	}

	// The client did not provide an IP address, use the IP address of the client.
	if host == "" {
		uri.Host = net.JoinHostPort(rhost, port)
		newRelay.URL = uri.String()
	} else if host != rhost {
		if debug {
			log.Println("IP address advertised does not match client IP address", r.RemoteAddr, uri)
		}
		http.Error(w, "IP address does not match client IP", http.StatusUnauthorized)
		return
	}
	newRelay.uri = uri

	for _, current := range permanentRelays {
		if current.uri.Host == newRelay.uri.Host {
			if debug {
				log.Println("Asked to add a relay", newRelay, "which exists in permanent list")
			}
			http.Error(w, "Invalid request", 500)
			return
		}
	}

	reschan := make(chan result)

	select {
	case requests <- request{newRelay, uri, reschan}:
		result := <-reschan
		if result.err != nil {
			http.Error(w, result.err.Error(), 500)
			return
		}
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		json.NewEncoder(w).Encode(map[string]time.Duration{
			"evictionIn": result.eviction,
		})

	default:
		if debug {
			log.Println("Dropping request")
		}
		w.WriteHeader(429)
	}
}

func requestProcessor() {
	for request := range requests {
		if debug {
			log.Println("Request for", request.relay)
		}
		if !client.TestRelay(request.uri, testCert, 250*time.Millisecond, 4) {
			if debug {
				log.Println("Test for relay", request.relay, "failed")
			}
			request.result <- result{fmt.Errorf("test failed"), 0}
			continue
		}

		mut.Lock()
		timer, ok := evictionTimers[request.relay.uri.Host]
		if ok {
			if debug {
				log.Println("Stopping existing timer for", request.relay)
			}
			timer.Stop()
		}

		for _, current := range knownRelays {
			if current.uri.Host == request.relay.uri.Host {
				if debug {
					log.Println("Relay", request.relay, "already exists")
				}
				goto found
			}
		}

		if debug {
			log.Println("Adding new relay", request.relay)
		}
		knownRelays = append(knownRelays, request.relay)

	found:
		evictionTimers[request.relay.uri.Host] = time.AfterFunc(evictionTime, evict(request.relay))
		mut.Unlock()
		request.result <- result{nil, evictionTime}
	}

}

func evict(relay relay) func() {
	return func() {
		mut.Lock()
		defer mut.Unlock()
		if debug {
			log.Println("Evicting", relay)
		}
		for i, current := range knownRelays {
			if current.uri.Host == relay.uri.Host {
				if debug {
					log.Println("Evicted", relay)
				}
				last := len(knownRelays) - 1
				knownRelays[i] = knownRelays[last]
				knownRelays = knownRelays[:last]
			}
		}
		delete(evictionTimers, relay.uri.Host)
	}
}

func limit(addr string, cache *lru.Cache, lock sync.RWMutex, rate time.Duration, burst int64) bool {
	host, _, err := net.SplitHostPort(addr)
	if err != nil {
		return false
	}

	lock.RLock()
	bkt, ok := cache.Get(host)
	lock.RUnlock()
	if ok {
		bkt := bkt.(*ratelimit.Bucket)
		if bkt.TakeAvailable(1) != 1 {
			// Rate limit
			return true
		}
	} else {
		lock.Lock()
		cache.Add(host, ratelimit.NewBucket(rate, burst))
		lock.Unlock()
	}
	return false
}

func loadPermanentRelays() {
	path, err := osext.ExecutableFolder()
	if err != nil {
		log.Println("Failed to locate executable directory")
		return
	}

	content, err := ioutil.ReadFile(filepath.Join(path, "relays"))
	if err != nil {
		return
	}

	for _, line := range strings.Split(string(content), "\n") {
		if len(line) == 0 {
			continue
		}

		uri, err := url.Parse(line)
		if err != nil {
			if debug {
				log.Println("Skipping permanent relay", line, "due to parse error", err)
			}
			continue
		}

		permanentRelays = append(permanentRelays, relay{
			URL: line,
			uri: uri,
		})
		if debug {
			log.Println("Adding permanent relay", line)
		}
	}
}

func loadOrCreateTestCertificate() {
	certFile, keyFile := filepath.Join(binDir, "cert.pem"), filepath.Join(binDir, "key.pem")
	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err == nil {
		testCert = []tls.Certificate{cert}
		return
	}

	cert, err = tlsutil.NewCertificate(certFile, keyFile, "relaypoolsrv", 3072)
	if err != nil {
		log.Fatalln("Failed to create test X509 key pair:", err)
	}
	testCert = []tls.Certificate{cert}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"runtime"
	"time"

	"github.com/jmoiron/sqlx"

	_ "github.com/lib/pq"
	"github.com/pavlik/fias_xml2postgresql/structures/actual_status"
	"github.com/pavlik/fias_xml2postgresql/structures/address_object"
	"github.com/pavlik/fias_xml2postgresql/structures/center_status"
	// "github.com/pavlik/fias_xml2postgresql/structures/center_status"
	// "github.com/pavlik/fias_xml2postgresql/structures/current_status"
	// "github.com/pavlik/fias_xml2postgresql/structures/estate_status"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Printf("Используемое количество ядер: %d\n", runtime.NumCPU())

	var format = flag.String("format", "xml", "File format for import (xml or dbf)")
	flag.Parse()

	// initialize the DbMap
	db := initDb()
	defer db.Close()

	var as_stat chan string = make(chan string)
	var ao_stat chan string = make(chan string)
	var cs_stat chan string = make(chan string)

	if *format == "xml" {
		fmt.Println("обработка XML-файлов")
		go actual_status.Export(as_stat, db, format)
		go address_object.Export(ao_stat, db, format)
		go center_status.Export(cs_stat, db, format)
		// current_status.Export(dbmap)
		// estate_status.Export(dbmap)

	} else if *format == "dbf" {
		// todo: обработка DBF-файлов
		fmt.Println("обработка DBF-файлов")
	}

	var msg1, msg2, msg3 string
	for {
		msg1 = <-as_stat
		msg2 = <-ao_stat
		msg3 = <-cs_stat
		progressPrint(msg1, msg2, msg3)
	}

	var input string
	fmt.Scanln(&input)
}

func progressPrint(msgs ...string) {
	var v string
	for _, v = range msgs {
		v = v + "\n"
	}

	fmt.Println(v)
	time.Sleep(time.Second * 1)
}

func initDb() *sqlx.DB {
	// connect to db using standard Go database/sql API
	// use whatever database/sql driver you wish
	db, err := sqlx.Open("postgres", "user=dev dbname=fias password=dev sslmode=disable")
	checkErr(err, "sqlx.Open failed")

	return db
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)
	}
}
<commit_msg>working with gorutines<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"runtime"
	"time"

	"github.com/jmoiron/sqlx"

	_ "github.com/lib/pq"
	"github.com/pavlik/fias_xml2postgresql/structures/actual_status"
	"github.com/pavlik/fias_xml2postgresql/structures/address_object"
	"github.com/pavlik/fias_xml2postgresql/structures/center_status"
	// "github.com/pavlik/fias_xml2postgresql/structures/center_status"
	// "github.com/pavlik/fias_xml2postgresql/structures/current_status"
	// "github.com/pavlik/fias_xml2postgresql/structures/estate_status"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Printf("Используемое количество ядер: %d\n", runtime.NumCPU())

	var format = flag.String("format", "xml", "File format for import (xml or dbf)")
	flag.Parse()

	// initialize the DbMap
	db := initDb()
	defer db.Close()

	var as_stat chan string = make(chan string, 1)
	var ao_stat chan string = make(chan string, 1)
	var cs_stat chan string = make(chan string, 1)

	if *format == "xml" {
		fmt.Println("обработка XML-файлов")
		go actual_status.Export(as_stat, db, format)
		go address_object.Export(ao_stat, db, format)
		go center_status.Export(cs_stat, db, format)
		// current_status.Export(dbmap)
		// estate_status.Export(dbmap)

	} else if *format == "dbf" {
		// todo: обработка DBF-файлов
		fmt.Println("обработка DBF-файлов")
	}

	var msg1, msg2, msg3 string
	for {
		select {
		case msg1 = <-as_stat:
		case msg2 = <-ao_stat:
		case msg3 = <-cs_stat:
		}
		progressPrint(msg1, msg2, msg3)
	}

	var input string
	fmt.Scanln(&input)
}

func progressPrint(msgs ...string) {
	var buffer bytes.Buffer

	for _, v := range msgs {
		buffer.WriteString(v)
		buffer.WriteString("\n")
	}

	fmt.Println(buffer.String())
	time.Sleep(time.Second * 1)
}

func initDb() *sqlx.DB {
	// connect to db using standard Go database/sql API
	// use whatever database/sql driver you wish
	db, err := sqlx.Open("postgres", "user=dev dbname=fias password=dev sslmode=disable")
	checkErr(err, "sqlx.Open failed")

	return db
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	"path/filepath"
	"regexp"
	"sync"
	"time"

	"github.com/178inaba/rainimg"
	"github.com/BurntSushi/toml"
	"github.com/golang/glog"
	"github.com/nlopes/slack"
)

const (
	settingToml = "setting.toml"
)

var (
	s   setting
	api *slack.Slack
	o   sync.Once

	fileMap = make(map[string]slack.File)
)

type setting struct {
	token `toml:"token"`
}

type token struct {
	User string `toml:"user"`
	Bot  string `toml:"bot"`
}

func init() {
	glog.Info("init()")

	flag.Parse()
}

func main() {
	glog.Info("main()")

	loadSetting()
	api = slack.New(s.token.User)

	userID, err := getUserID()
	if err != nil {
		os.Exit(1)
	}

	getFileList(userID)
	postRainImg()
}

func loadSetting() {
	glog.Info("loadSetting()")

	_, err := toml.DecodeFile(settingToml, &s)
	if err != nil {
		glog.Error("load error: ", err)
	}
}

func getUserID() (string, error) {
	glog.Info("getUserID()")

	info, err := api.AuthTest()
	if err != nil {
		glog.Error("AuthTest Error: ", err)
		return "", err
	}

	glog.Info("User: ", info.User)
	glog.Info("UserId: ", info.UserId)

	return info.UserId, nil
}

func getFileList(userID string) {
	glog.Info("getFileList()")

	searchParam := slack.NewGetFilesParameters()
	searchParam.UserId = userID

	files, _, _ := api.GetFiles(searchParam)

	glog.Info("filename list:")
	for _, file := range files {
		fileMap[file.Name] = file
		glog.Info(file.Name)
	}
}

func postRainImg() {
	glog.Info("postRainImg()")

	botAPI := slack.New(s.token.Bot)
	sendCh := make(chan slack.OutgoingMessage)
	eventCh := make(chan slack.SlackEvent)

	ws, err := botAPI.StartRTM("", "https://slack.com/")
	if err != nil {
		glog.Error(err)
		return
	}

	go ws.HandleIncomingEvents(eventCh)
	go ws.Keepalive(20 * time.Second)
	go func(ws *slack.SlackWS, sendCh <-chan slack.OutgoingMessage) {
		for {
			om := <-sendCh
			ws.SendMessage(&om)
		}
	}(ws, sendCh)

	for {
		event := <-eventCh
		switch event.Data.(type) {
		case *slack.MessageEvent:
			msg := event.Data.(*slack.MessageEvent)
			glog.Info("channel id: ", msg.ChannelId)
			glog.Info("text: ", msg.Text)

			match, _ := regexp.MatchString("雨", msg.Text)
			if match {
				f := rainImgUpload()
				sendCh <- *ws.NewOutgoingMessage(f.URL, msg.ChannelId)
			}
		case slack.LatencyReport:
			latency := event.Data.(slack.LatencyReport)
			glog.Info("ping latency: ", latency.Value)
		}
	}
}

func rainImgUpload() slack.File {
	glog.Info("rainImgUpload()")

	// create image
	fPath := rainimg.GetImgPath()

	// get filename
	fileName := filepath.Base(fPath)

	// already uploaded check
	file, ok := fileMap[fileName]
	if ok {
		glog.Info("already uploaded: ", file.Name)
		return file
	}

	// file up param
	var fup slack.FileUploadParameters
	fup.File = fPath

	// upload
	upFile, _ := api.UploadFile(fup)
	glog.Info("upload file: ", upFile.Name)

	// add file list
	fileMap[upFile.Name] = *upFile

	return *upFile
}
<commit_msg>fix nlopes/slack rename<commit_after>package main

import (
	"flag"
	"os"
	"path/filepath"
	"regexp"
	"sync"
	"time"

	"github.com/178inaba/rainimg"
	"github.com/BurntSushi/toml"
	"github.com/golang/glog"
	"github.com/nlopes/slack"
)

const (
	settingToml = "setting.toml"
)

var (
	s   setting
	api *slack.Slack
	o   sync.Once

	fileMap = make(map[string]slack.File)
)

type setting struct {
	token `toml:"token"`
}

type token struct {
	User string `toml:"user"`
	Bot  string `toml:"bot"`
}

func init() {
	glog.Info("init()")

	flag.Parse()
}

func main() {
	glog.Info("main()")

	loadSetting()
	api = slack.New(s.token.User)

	userID, err := getUserID()
	if err != nil {
		os.Exit(1)
	}

	getFileList(userID)
	postRainImg()
}

func loadSetting() {
	glog.Info("loadSetting()")

	_, err := toml.DecodeFile(settingToml, &s)
	if err != nil {
		glog.Error("load error: ", err)
	}
}

func getUserID() (string, error) {
	glog.Info("getUserID()")

	info, err := api.AuthTest()
	if err != nil {
		glog.Error("AuthTest Error: ", err)
		return "", err
	}

	glog.Info("User: ", info.User)
	glog.Info("UserId: ", info.UserID)

	return info.UserID, nil
}

func getFileList(userID string) {
	glog.Info("getFileList()")

	searchParam := slack.NewGetFilesParameters()
	searchParam.User = userID

	files, _, _ := api.GetFiles(searchParam)

	glog.Info("filename list:")
	for _, file := range files {
		fileMap[file.Name] = file
		glog.Info(file.Name)
	}
}

func postRainImg() {
	glog.Info("postRainImg()")

	botAPI := slack.New(s.token.Bot)
	sendCh := make(chan slack.OutgoingMessage)
	eventCh := make(chan slack.SlackEvent)

	ws, err := botAPI.StartRTM("", "https://slack.com/")
	if err != nil {
		glog.Error(err)
		return
	}

	go ws.HandleIncomingEvents(eventCh)
	go ws.Keepalive(20 * time.Second)
	go func(ws *slack.WS, sendCh <-chan slack.OutgoingMessage) {
		for {
			om := <-sendCh
			ws.SendMessage(&om)
		}
	}(ws, sendCh)

	for {
		event := <-eventCh
		switch event.Data.(type) {
		case *slack.MessageEvent:
			msg := event.Data.(*slack.MessageEvent)
			glog.Info("channel: ", msg.Channel)
			glog.Info("text: ", msg.Text)

			match, _ := regexp.MatchString("雨", msg.Text)
			if match {
				f := rainImgUpload()
				sendCh <- *ws.NewOutgoingMessage(f.URL, msg.Channel)
			}
		case slack.LatencyReport:
			latency := event.Data.(slack.LatencyReport)
			glog.Info("ping latency: ", latency.Value)
		}
	}
}

func rainImgUpload() slack.File {
	glog.Info("rainImgUpload()")

	// create image
	fPath := rainimg.GetImgPath()

	// get filename
	fileName := filepath.Base(fPath)

	// already uploaded check
	file, ok := fileMap[fileName]
	if ok {
		glog.Info("already uploaded: ", file.Name)
		return file
	}

	// file up param
	var fup slack.FileUploadParameters
	fup.File = fPath

	// upload
	upFile, _ := api.UploadFile(fup)
	glog.Info("upload file: ", upFile.Name)

	// add file list
	fileMap[upFile.Name] = *upFile

	return *upFile
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/zmj/sfslack/log"

	"os"

	"time"

	"github.com/zmj/sfslack/server"
)

func main() {
	cfg := server.Config{}
	flag.StringVar(&cfg.Host, "host", "", "Public host address")
	flag.IntVar(&cfg.Port, "port", 8080, "Listen Port")
	flag.StringVar(&cfg.SfOAuthID, "sfoauthid", "", "ShareFile OAuth Client ID")
	flag.StringVar(&cfg.SfOAuthSecret, "sfoauthsecret", "", "ShareFile OAuth Client Secret")
	flag.StringVar(&cfg.SlackVerificationToken, "slackverifytoken", "", "Slack command verification token")
	flag.Parse()
	// validate before open log, not in server

	logFileName := fmt.Sprintf("%v.log", time.Now().String())
	logfile, err := os.Open(logFileName) // from args?
	if err != nil {
		err = fmt.Errorf("Failed to create log file\n%v", err)
		fmt.Println(err.Error)
		return
	}
	srv, err := server.NewServer(cfg, log.New(logfile, true))
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	err = srv.ListenAndServe()
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
<commit_msg>stuff<commit_after>package main

import (
	"flag"
	"fmt"

	"github.com/zmj/sfslack/log"

	"os"

	"time"

	"github.com/zmj/sfslack/server"
)

func main() {
	cfg := server.Config{}
	flag.StringVar(&cfg.Host, "host", "", "Public host address")
	flag.IntVar(&cfg.Port, "port", 8080, "Listen Port")
	flag.StringVar(&cfg.SfOAuthID, "sfoauthid", "", "ShareFile OAuth Client ID")
	flag.StringVar(&cfg.SfOAuthSecret, "sfoauthsecret", "", "ShareFile OAuth Client Secret")
	flag.StringVar(&cfg.SlackVerificationToken, "slackverifytoken", "", "Slack command verification token")
	flag.Parse()
	// validate before open log, not in server

	logFileName := fmt.Sprintf("%v.log", time.Now().Format(time.Stamp))
	logfile, err := os.Open(logFileName) // from args?
	if err != nil {
		err = fmt.Errorf("Failed to create log file\n%v", err)
		fmt.Println(err.Error())
		return
	}
	srv, err := server.NewServer(cfg, log.New(logfile, true))
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	err = srv.ListenAndServe()
	if err != nil {
		fmt.Println(err.Error())
		return
	}
}
<|endoftext|>


<commit_before>// Package c2go contains the main function for running the executable.
//
// Installation
//
//     go get -u github.com/elliotchance/c2go
//
// Usage
//
//     c2go myfile.c
//
package main

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

	"errors"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/preprocessor"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.18.3 Tantalum 2017-12-09"

var stderr io.Writer = os.Stderr

// ProgramArgs defines the options available when processing the program. There
// is no constructor since the zeroed out values are the appropriate defaults -
// you need only set the options you need.
//
// TODO: Better separation on CLI modes
// https://github.com/elliotchance/c2go/issues/134
//
// Do not instantiate this directly. Instead use DefaultProgramArgs(); then
// modify any specific attributes.
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFiles  []string
	clangFlags  []string
	outputFile  string
	packageName string

	// A private option to output the Go as a *_test.go file.
	outputAsTest bool
}

// DefaultProgramArgs default value of ProgramArgs
func DefaultProgramArgs() ProgramArgs {
	return ProgramArgs{
		verbose:      false,
		ast:          false,
		packageName:  "main",
		clangFlags:   []string{},
		outputAsTest: false,
	}
}

func readAST(data []byte) []string {
	return strings.Split(string(data), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := make([]treeNode, len(lines))
	var counter int
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)
		trimmed := strings.TrimLeft(line, "|\\- `")
		node := ast.Parse(trimmed)
		indentLevel := (len(line) - len(trimmed)) / 2
		nodes[counter] = treeNode{indentLevel, node}
		counter++
	}
	nodes = nodes[0:counter]

	return nodes
}

func convertLinesToNodesParallel(lines []string) []treeNode {
	// function f separate full list on 2 parts and
	// then each part can recursive run function f
	var f func([]string, int) []treeNode

	f = func(lines []string, deep int) []treeNode {
		deep = deep - 2
		part := len(lines) / 2

		var tr1 = make(chan []treeNode)
		var tr2 = make(chan []treeNode)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr1 <- convertLinesToNodes(lines)
				return
			}
			tr1 <- f(lines, deep)
		}(lines[0:part], deep)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr2 <- convertLinesToNodes(lines)
				return
			}
			tr2 <- f(lines, deep)
		}(lines[part:], deep)

		defer close(tr1)
		defer close(tr2)

		return append(<-tr1, <-tr2...)
	}

	// Parameter of deep - can be any, but effective to use
	// same amount of CPU
	return f(lines, runtime.NumCPU())
}

// buildTree converts an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a tree with its own
	// root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

// Start begins transpiling an input file.
func Start(args ProgramArgs) (err error) {
	if args.verbose {
		fmt.Println("Start tanspiling ...")
	}

	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	for _, in := range args.inputFiles {
		_, err := os.Stat(in)
		if err != nil {
			return fmt.Errorf("Input file %s is not found", in)
		}
	}

	// 2. Preprocess
	if args.verbose {
		fmt.Println("Running clang preprocessor...")
	}

	pp, err := preprocessor.Analyze(args.inputFiles, args.clangFlags)
	if err != nil {
		return err
	}

	if args.verbose {
		fmt.Println("Writing preprocessor ...")
	}
	dir, err := ioutil.TempDir("", "c2go")
	if err != nil {
		return fmt.Errorf("Cannot create temp folder: %v", err)
	}
	defer os.RemoveAll(dir) // clean up

	ppFilePath := path.Join(dir, "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to %s failed: %v", ppFilePath, err)
	}

	// 3. Generate JSON from AST
	if args.verbose {
		fmt.Println("Running clang for AST tree...")
	}
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", "-fno-color-diagnostics", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	if args.verbose {
		fmt.Println("Reading clang AST tree...")
	}
	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()

		return nil
	}

	p := program.NewProgram()
	p.Verbose = args.verbose
	p.OutputAsTest = args.outputAsTest

	// Converting to nodes
	if args.verbose {
		fmt.Println("Converting to nodes...")
	}
	nodes := convertLinesToNodesParallel(lines)

	// build tree
	if args.verbose {
		fmt.Println("Building tree...")
	}
	tree := buildTree(nodes, 0)
	ast.FixPositions(tree)

	// Repair the floating literals. See RepairFloatingLiteralsFromSource for
	// more information.
	floatingErrors := ast.RepairFloatingLiteralsFromSource(tree[0], ppFilePath)

	for _, fErr := range floatingErrors {
		message := fmt.Sprintf("could not read exact floating literal: %s",
			fErr.Err.Error())
		p.AddMessage(p.GenerateWarningMessage(errors.New(message), fErr.Node))
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		// Choose inputFile for creating name of output file
		input := args.inputFiles[0]
		// We choose name for output Go code at the base
		// on filename for choosed input file
		cleanFileName := filepath.Clean(filepath.Base(input))
		extension := filepath.Ext(input)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	// transpile ast tree
	if args.verbose {
		fmt.Println("Transpiling tree...")
	}

	err = transpiler.TranspileAST(args.outputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		return fmt.Errorf("cannot transpile AST : %v", err)
	}

	// write the output Go code
	if args.verbose {
		fmt.Println("Writing the output Go code...")
	}
	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0644)
	if err != nil {
		return fmt.Errorf("writing Go output file failed: %v", err)
	}

	return nil
}

type inputDataFlags []string

func (i *inputDataFlags) String() (s string) {
	for pos, item := range *i {
		s += fmt.Sprintf("Flag %d. %s\n", pos, item)
	}
	return
}

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

var clangFlags inputDataFlags

func init() {
	transpileCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
}

var (
	versionFlag       = flag.Bool("v", false, "print the version and exit")
	transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
	verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
	outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
	packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
	transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
	astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
	astHelpFlag       = astCommand.Bool("h", false, "print help information")
)

func main() {
	code := runCommand()
	if code != 0 {
		os.Exit(code)
	}
}

func runCommand() int {

	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file or files to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	transpileCommand.SetOutput(stderr)
	astCommand.SetOutput(stderr)

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return 0
	}

	if flag.NArg() < 1 {
		flag.Usage()
		return 1
	}

	args := DefaultProgramArgs()

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			return 1
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			return 1
		}

		args.ast = true
		args.inputFiles = astCommand.Args()
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			return 1
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
			transpileCommand.PrintDefaults()
			return 1
		}

		args.inputFiles = transpileCommand.Args()
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
		args.verbose = *verboseFlag
		args.clangFlags = clangFlags
	default:
		flag.Usage()
		return 1
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}

	return 0
}
<commit_msg>Bump version: v0.18.4 Tantalum 2017-12-10<commit_after>// Package c2go contains the main function for running the executable.
//
// Installation
//
//     go get -u github.com/elliotchance/c2go
//
// Usage
//
//     c2go myfile.c
//
package main

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

	"errors"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/preprocessor"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.18.4 Tantalum 2017-12-10"

var stderr io.Writer = os.Stderr

// ProgramArgs defines the options available when processing the program. There
// is no constructor since the zeroed out values are the appropriate defaults -
// you need only set the options you need.
//
// TODO: Better separation on CLI modes
// https://github.com/elliotchance/c2go/issues/134
//
// Do not instantiate this directly. Instead use DefaultProgramArgs(); then
// modify any specific attributes.
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFiles  []string
	clangFlags  []string
	outputFile  string
	packageName string

	// A private option to output the Go as a *_test.go file.
	outputAsTest bool
}

// DefaultProgramArgs default value of ProgramArgs
func DefaultProgramArgs() ProgramArgs {
	return ProgramArgs{
		verbose:      false,
		ast:          false,
		packageName:  "main",
		clangFlags:   []string{},
		outputAsTest: false,
	}
}

func readAST(data []byte) []string {
	return strings.Split(string(data), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := make([]treeNode, len(lines))
	var counter int
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)
		trimmed := strings.TrimLeft(line, "|\\- `")
		node := ast.Parse(trimmed)
		indentLevel := (len(line) - len(trimmed)) / 2
		nodes[counter] = treeNode{indentLevel, node}
		counter++
	}
	nodes = nodes[0:counter]

	return nodes
}

func convertLinesToNodesParallel(lines []string) []treeNode {
	// function f separate full list on 2 parts and
	// then each part can recursive run function f
	var f func([]string, int) []treeNode

	f = func(lines []string, deep int) []treeNode {
		deep = deep - 2
		part := len(lines) / 2

		var tr1 = make(chan []treeNode)
		var tr2 = make(chan []treeNode)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr1 <- convertLinesToNodes(lines)
				return
			}
			tr1 <- f(lines, deep)
		}(lines[0:part], deep)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr2 <- convertLinesToNodes(lines)
				return
			}
			tr2 <- f(lines, deep)
		}(lines[part:], deep)

		defer close(tr1)
		defer close(tr2)

		return append(<-tr1, <-tr2...)
	}

	// Parameter of deep - can be any, but effective to use
	// same amount of CPU
	return f(lines, runtime.NumCPU())
}

// buildTree converts an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a tree with its own
	// root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

// Start begins transpiling an input file.
func Start(args ProgramArgs) (err error) {
	if args.verbose {
		fmt.Println("Start tanspiling ...")
	}

	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	for _, in := range args.inputFiles {
		_, err := os.Stat(in)
		if err != nil {
			return fmt.Errorf("Input file %s is not found", in)
		}
	}

	// 2. Preprocess
	if args.verbose {
		fmt.Println("Running clang preprocessor...")
	}

	pp, err := preprocessor.Analyze(args.inputFiles, args.clangFlags)
	if err != nil {
		return err
	}

	if args.verbose {
		fmt.Println("Writing preprocessor ...")
	}
	dir, err := ioutil.TempDir("", "c2go")
	if err != nil {
		return fmt.Errorf("Cannot create temp folder: %v", err)
	}
	defer os.RemoveAll(dir) // clean up

	ppFilePath := path.Join(dir, "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to %s failed: %v", ppFilePath, err)
	}

	// 3. Generate JSON from AST
	if args.verbose {
		fmt.Println("Running clang for AST tree...")
	}
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", "-fno-color-diagnostics", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	if args.verbose {
		fmt.Println("Reading clang AST tree...")
	}
	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()

		return nil
	}

	p := program.NewProgram()
	p.Verbose = args.verbose
	p.OutputAsTest = args.outputAsTest

	// Converting to nodes
	if args.verbose {
		fmt.Println("Converting to nodes...")
	}
	nodes := convertLinesToNodesParallel(lines)

	// build tree
	if args.verbose {
		fmt.Println("Building tree...")
	}
	tree := buildTree(nodes, 0)
	ast.FixPositions(tree)

	// Repair the floating literals. See RepairFloatingLiteralsFromSource for
	// more information.
	floatingErrors := ast.RepairFloatingLiteralsFromSource(tree[0], ppFilePath)

	for _, fErr := range floatingErrors {
		message := fmt.Sprintf("could not read exact floating literal: %s",
			fErr.Err.Error())
		p.AddMessage(p.GenerateWarningMessage(errors.New(message), fErr.Node))
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		// Choose inputFile for creating name of output file
		input := args.inputFiles[0]
		// We choose name for output Go code at the base
		// on filename for choosed input file
		cleanFileName := filepath.Clean(filepath.Base(input))
		extension := filepath.Ext(input)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	// transpile ast tree
	if args.verbose {
		fmt.Println("Transpiling tree...")
	}

	err = transpiler.TranspileAST(args.outputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		return fmt.Errorf("cannot transpile AST : %v", err)
	}

	// write the output Go code
	if args.verbose {
		fmt.Println("Writing the output Go code...")
	}
	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0644)
	if err != nil {
		return fmt.Errorf("writing Go output file failed: %v", err)
	}

	return nil
}

type inputDataFlags []string

func (i *inputDataFlags) String() (s string) {
	for pos, item := range *i {
		s += fmt.Sprintf("Flag %d. %s\n", pos, item)
	}
	return
}

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

var clangFlags inputDataFlags

func init() {
	transpileCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
}

var (
	versionFlag       = flag.Bool("v", false, "print the version and exit")
	transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
	verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
	outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
	packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
	transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
	astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
	astHelpFlag       = astCommand.Bool("h", false, "print help information")
)

func main() {
	code := runCommand()
	if code != 0 {
		os.Exit(code)
	}
}

func runCommand() int {

	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file or files to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	transpileCommand.SetOutput(stderr)
	astCommand.SetOutput(stderr)

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return 0
	}

	if flag.NArg() < 1 {
		flag.Usage()
		return 1
	}

	args := DefaultProgramArgs()

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			return 1
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			return 1
		}

		args.ast = true
		args.inputFiles = astCommand.Args()
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			return 1
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
			transpileCommand.PrintDefaults()
			return 1
		}

		args.inputFiles = transpileCommand.Args()
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
		args.verbose = *verboseFlag
		args.clangFlags = clangFlags
	default:
		flag.Usage()
		return 1
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}

	return 0
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"

	"github.com/dasfoo/i2c"
	"github.com/dasfoo/lidar-lite-v2"
)

func main() {
	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
	bus, _ := i2c.NewBus(1)
	s := lidar.NewLidar(bus, lidar.DefaultAddress)

	fmt.Println(s.GetDistance())

	if hw, sw, err := s.GetVersion(); err == nil {
		fmt.Printf("LIDAR-Lite v2 \"Blue Label\" hw%dsw%d\n", hw, sw)
	}
}
<commit_msg>Demo for LIDAR, BPi and concurrency<commit_after>package main

import (
	"fmt"
	"log"
	"time"

	"github.com/dasfoo/bright-pi"
	"github.com/dasfoo/i2c"
	"github.com/dasfoo/lidar-lite-v2"
)

func ledCircle(b *bpi.BrightPI, circles int) {
	leds := []byte{bpi.WhiteTopLeft, bpi.WhiteTopRight, bpi.WhiteBottomRight, bpi.WhiteBottomLeft}
	for i := 0; i < circles; i++ {
		for _, led := range leds {
			_ = b.Power(led)
			time.Sleep(50 * time.Millisecond)
		}
	}
}

func main() {
	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
	bus, err := i2c.NewBus(1)
	if err != nil {
		log.Println(err)
		return
	}

	b := bpi.NewBrightPI(bus, bpi.DefaultAddress)
	s := lidar.NewLidar(bus, lidar.DefaultAddress)

	_ = b.Dim(bpi.WhiteAll, bpi.DefaultDim)
	_ = b.Gain(bpi.DefaultGain)
	go ledCircle(b, 16)

	for i := 0; i < 32; i++ {
		if d, e := s.GetDistance(); e == nil {
			fmt.Println("Distance is", d, "cm")
		}
		time.Sleep(100 * time.Millisecond)
	}

	if hw, sw, err := s.GetVersion(); err == nil {
		fmt.Printf("LIDAR-Lite v2 \"Blue Label\" hw%dsw%d\n", hw, sw)
	}

	// Put devices in low power consumption mode
	_ = s.Sleep()
	_ = b.Sleep()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"strconv"
	"strings"

	"github.com/fatih/color"
)

var textTypes = []string{
	"plain",
	"json",
	"html",
}

var currentPage int

func lineCounter(file string) (int, error) {

	f, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	buf := make([]byte, 32*1024)
	count := 1
	lineSep := []byte{'\n'}

	for {
		c, err := f.Read(buf)
		count += bytes.Count(buf[:c], lineSep)

		switch {
		case err == io.EOF:
			return count, nil

		case err != nil:
			return count, err
		}
	}
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func exitWithError(s string) {
	io.WriteString(os.Stderr, s)
	os.Exit(1)
}

func parseFile(file string, page, lines int) {

	f, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	s := bufio.NewScanner(f)

	current := 0

	var output bytes.Buffer

	skip := (page - 1) * lines

	for s.Scan() {
		if current >= skip {
			output.WriteString(s.Text() + "\n")
		}
		current++
		if current >= lines+skip {
			break
		}
	}

	if err := s.Err(); err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.String())
}

func main() {
	file := flag.String("file", "", "File path")
	text := flag.String("text", "plain", "Text type to parse. Defaults to plain")
	lines := flag.Int("lines", 100, "Number of lines per page. Defaults to 100")
	page := flag.Int("page", 1, "Current page number. Defaults to 1")
	noColor := flag.Bool("no-color", false, "Disable color output. Defaults to false")
	// search := flag.String("search", "", "Text to filter")

	flag.Parse()

	if *noColor {
		color.NoColor = true // disables colorized output
	}

	// success := color.New(color.FgBlack, color.BgGreen, color.Bold).SprintFunc()

	fail := color.New(color.FgWhite, color.BgRed).SprintFunc()

	next := color.New(color.FgBlack, color.BgYellow).SprintFunc()

	if !stringInSlice(*text, textTypes) {
		exitWithError(fail(fmt.Sprintf("Error! Accepted text types are: %s", strings.Join(textTypes, ", "))))
	}

	if *file == "" {
		exitWithError(fail("Error! File is required"))
	}

	currentPage := *page

	n, err := lineCounter(*file)

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

	pages := float64(n) / float64(*lines)

	pages = math.Ceil(pages)

	numPages := int(pages)

	fmt.Println()

	parseFile(*file, currentPage, *lines)

	fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")

	in := bufio.NewScanner(os.Stdin)

	for in.Scan() {
		inputPage, err := strconv.Atoi(in.Text())
		if err != nil {
			log.Print(fail("Error! A valid number is required"))
			fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
		} else {
			if inputPage > numPages {
				log.Print(fail(fmt.Sprintf("Error! Page number cannot be greater than %d", numPages)))
				fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
			} else if inputPage < 1 {
				log.Print(fail("Error! Page number cannot be smaller than 1"))
				fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
			} else {
				currentPage = inputPage
				fmt.Println()
				parseFile(*file, currentPage, *lines)
				fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
			}
		}
	}

	if err := in.Err(); err != nil {
		log.Fatal(err)
	}

}
<commit_msg>Refactored parseFile function<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"strconv"
	"strings"

	"github.com/fatih/color"
)

var textTypes = []string{
	"plain",
	"json",
	"html",
}

var currentPage int

func lineCounter(file string) (int, error) {

	f, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	buf := make([]byte, 32*1024)
	count := 1
	lineSep := []byte{'\n'}

	for {
		c, err := f.Read(buf)
		count += bytes.Count(buf[:c], lineSep)

		switch {
		case err == io.EOF:
			return count, nil

		case err != nil:
			return count, err
		}
	}
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func exitWithError(s string) {
	io.WriteString(os.Stderr, s)
	os.Exit(1)
}

func parseFile(file string, page, lines int) string {

	f, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	s := bufio.NewScanner(f)

	current := 0

	var output bytes.Buffer

	skip := (page - 1) * lines

	for s.Scan() {
		if current >= skip {
			output.WriteString(s.Text() + "\n")
		}
		current++
		if current >= lines+skip {
			break
		}
	}

	if err := s.Err(); err != nil {
		log.Fatal(err)
	}

	return output.String()
}

func main() {
	file := flag.String("file", "", "File path")
	text := flag.String("text", "plain", "Text type to parse. Defaults to plain")
	lines := flag.Int("lines", 100, "Number of lines per page. Defaults to 100")
	page := flag.Int("page", 1, "Current page number. Defaults to 1")
	noColor := flag.Bool("no-color", false, "Disable color output. Defaults to false")
	// filter := flag.String("filter", "", "Text to filter")

	flag.Parse()

	if *noColor {
		color.NoColor = true // disables colorized output
	}

	// success := color.New(color.FgBlack, color.BgGreen, color.Bold).SprintFunc()

	fail := color.New(color.FgWhite, color.BgRed).SprintFunc()

	next := color.New(color.FgBlack, color.BgYellow).SprintFunc()

	if !stringInSlice(*text, textTypes) {
		exitWithError(fail(fmt.Sprintf("Error! Accepted text types are: %s", strings.Join(textTypes, ", "))))
	}

	if *file == "" {
		exitWithError(fail("Error! File is required"))
	}

	currentPage := *page

	n, err := lineCounter(*file)

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

	pages := float64(n) / float64(*lines)

	pages = math.Ceil(pages)

	numPages := int(pages)

	fmt.Println()

	output := parseFile(*file, currentPage, *lines)

	fmt.Println(output)

	fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")

	in := bufio.NewScanner(os.Stdin)

	for in.Scan() {
		inputPage, err := strconv.Atoi(in.Text())
		if err != nil {
			log.Print(fail("Error! A valid number is required"))
			fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
		} else {
			if inputPage > numPages {
				log.Print(fail(fmt.Sprintf("Error! Page number cannot be greater than %d", numPages)))
				fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
			} else if inputPage < 1 {
				log.Print(fail("Error! Page number cannot be smaller than 1"))
				fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
			} else {
				currentPage = inputPage
				fmt.Println()
				output := parseFile(*file, currentPage, *lines)
				fmt.Println(output)
				fmt.Print(next(fmt.Sprintf("Page %d/%d. Enter page number to navigate or press Ctrl+C to quit:", currentPage, numPages)), " ")
			}
		}
	}

	if err := in.Err(); err != nil {
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//
package main

import (
	"flag"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"text/template"
)

const SEP = string(os.PathSeparator)

var (
	httpAddr    = flag.String("http", ":8080", "http service address")
	httpsAddr   = flag.String("https", ":8090", "https service address")
	hostname    = flag.String("host", "localhost", "domain or host name")
	work        = flag.String("work", "work", "working directory")
	users       = flag.String("users", "users", "users root folder")
	certFile    = flag.String("cert", "cert.pem", "SSL certificate file")
	keyFile     = flag.String("key", "key.pem", "SSL key file")
	public      = flag.String("public", "public", "public web directory")
	clientTempl *template.Template
)

// isTLS checks for TLS and returns true if handshake is complete or false if not.
func isTLS(r *http.Request) bool {
	if r.TLS != nil && r.TLS.HandshakeComplete {
		return true
	}
	return false
}

// getArgs splits a slice of bytes into a slice of string arguments.
//Anything in '', "", or `` are consider a single argument (including spaces).
func getArgs(b []byte) (s []string) {
	re := regexp.MustCompile("`([\\S\\s]*)`|('([\\S \\t\\r]*)'|\"([\\S ]*)\"|\\S+)")
	args := re.FindAllSubmatch(b, -1)
	for _, val := range args {
		s = append(s, string(val[0]))
	}
	return
}

// serveWs serves the websocket and starts the listener on successful connection.
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if r.Header.Get("Origin") != "https://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	defer ws.Close()
	var c = client{ws: ws, address: ws.RemoteAddr().String(), user: user{Name: "Guest"}}
	log.Println(c.address, r.URL, "connected")
	c.innerHTML("#status-box", ""+c.user.Name+"")
	e := c.listener()
	if e != nil && e != io.EOF {
		log.Println(e)
	}
	log.Println(c.address, "disconnected")
}

func serveClient(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.TLS == nil {
		log.Println("redirecting")
		http.Redirect(w, r, "https://"+*hostname+*httpsAddr, 301)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	type data struct {
		SockUrl, Status string
	}
	sockUrl := "wss://" + *hostname + *httpsAddr + "/ws"
	clientTempl.Execute(w, data{SockUrl: sockUrl})
}

func init() {
	flag.Parse()
	dirs := map[string]os.FileMode{*work: 0700, *public: 0755, *users: 0700}
	for path, perm := range dirs {
		if pathExists(path) {
			err := os.Chmod(path, perm)
			if err != nil {
				log.Fatal(err)
			}
		} else {
			err := os.Mkdir(path, perm)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
	for _, file := range []*string{certFile, keyFile} {
		_, err := os.Stat(*file)
		if os.IsNotExist(err) {
			path := *work + SEP + *file
			_, err := os.Stat(path)
			if err != nil {
				log.Fatal(err)
			}
			*file = path
		}
	}
	clientTempl = template.Must(template.ParseFiles(*public + SEP + "client.html"))
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", serveClient)
	r.HandleFunc("/ws", serveWs)
	http.Handle("/", r)
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir(*public))))
	go func() {
		// cert.pem is ssl.crt + *server.ca.pem
		err := http.ListenAndServeTLS(*httpsAddr, *certFile, *keyFile, nil)
		if err != nil {
			log.Fatal("ListenAndServeTLS:", err)
		}
	}()
	err := http.ListenAndServe(*httpAddr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Added logging for Referer, URL, etc on initial connect.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//
package main

import (
	"flag"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"text/template"
)

const SEP = string(os.PathSeparator)

var (
	httpAddr    = flag.String("http", ":8080", "http service address")
	httpsAddr   = flag.String("https", ":8090", "https service address")
	hostname    = flag.String("host", "localhost", "domain or host name")
	work        = flag.String("work", "work", "working directory")
	users       = flag.String("users", "users", "users root folder")
	certFile    = flag.String("cert", "cert.pem", "SSL certificate file")
	keyFile     = flag.String("key", "key.pem", "SSL key file")
	public      = flag.String("public", "public", "public web directory")
	clientTempl *template.Template
)

// isTLS checks for TLS and returns true if handshake is complete or false if not.
func isTLS(r *http.Request) bool {
	if r.TLS != nil && r.TLS.HandshakeComplete {
		return true
	}
	return false
}

// getArgs splits a slice of bytes into a slice of string arguments.
//Anything in '', "", or `` are consider a single argument (including spaces).
func getArgs(b []byte) (s []string) {
	re := regexp.MustCompile("`([\\S\\s]*)`|('([\\S \\t\\r]*)'|\"([\\S ]*)\"|\\S+)")
	args := re.FindAllSubmatch(b, -1)
	for _, val := range args {
		s = append(s, string(val[0]))
	}
	return
}

// serveWs serves the websocket and starts the listener on successful connection.
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if r.Header.Get("Origin") != "https://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	defer ws.Close()
	var c = client{ws: ws, address: ws.RemoteAddr().String(), user: user{Name: "Guest"}}
	log.Println(c.address, r.URL, "connected")
	c.innerHTML("#status-box", ""+c.user.Name+"")
	e := c.listener()
	if e != nil && e != io.EOF {
		log.Println(e)
	}
	log.Println(c.address, "disconnected")
}

// serveClient is the handler that serves the client html on initial connection.
func serveClient(w http.ResponseWriter, r *http.Request) {
	log.Println(r.RemoteAddr, r.Referer(), r.URL, "connecting")
	if r.URL.Path != "/" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.TLS == nil {
		log.Println("redirecting")
		http.Redirect(w, r, "https://"+*hostname+*httpsAddr, 301)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method nod allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	type data struct {
		SockUrl, Status string
	}
	sockUrl := "wss://" + *hostname + *httpsAddr + "/ws"
	clientTempl.Execute(w, data{SockUrl: sockUrl})
}

func init() {
	flag.Parse()
	dirs := map[string]os.FileMode{*work: 0700, *public: 0755, *users: 0700}
	for path, perm := range dirs {
		if pathExists(path) {
			err := os.Chmod(path, perm)
			if err != nil {
				log.Fatal(err)
			}
		} else {
			err := os.Mkdir(path, perm)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
	for _, file := range []*string{certFile, keyFile} {
		_, err := os.Stat(*file)
		if os.IsNotExist(err) {
			path := *work + SEP + *file
			_, err := os.Stat(path)
			if err != nil {
				log.Fatal(err)
			}
			*file = path
		}
	}
	clientTempl = template.Must(template.ParseFiles(*public + SEP + "client.html"))
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", serveClient)
	r.HandleFunc("/ws", serveWs)
	http.Handle("/", r)
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir(*public))))
	go func() {
		// cert.pem is ssl.crt + *server.ca.pem
		err := http.ListenAndServeTLS(*httpsAddr, *certFile, *keyFile, nil)
		if err != nil {
			log.Fatal("ListenAndServeTLS:", err)
		}
	}()
	err := http.ListenAndServe(*httpAddr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base32"
	"fmt"
	"os"
	"strings"
	"time"
)

func toBytes(value int64) []byte {
	var result []byte
	mask := int64(0xFF)
	shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
	for _, shift := range shifts {
		result = append(result, byte((value>>shift)&mask))
	}
	return result
}

func toUint32(bytes []byte) uint32 {
	return (uint32(bytes[0]) << 24) + (uint32(bytes[1]) << 16) +
		(uint32(bytes[2]) << 8) + uint32(bytes[3])
}

func oneTimePassword(key []byte, value []byte) uint32 {
	// sign the value using HMAC-SHA1
	hmacSha1 := hmac.New(sha1.New, key)
	hmacSha1.Write(value)
	hash := hmacSha1.Sum(nil)

	// We're going to use a subset of the generated hash.
	// Using the last nibble (half-byte) to choose the index to start from.
	// This number is always appropriate as it's maximum decimal 15, the hash will
	// have the maximum index 19 (20 bytes of SHA1) and we need 4 bytes.
	offset := hash[len(hash)-1] & 0x0F

	// get a 32-bit (4-byte) chunk from the hash starting at offset
	hashParts := hash[offset : offset+4]

	// ignore the most significant bit as per RFC 4226
	hashParts[0] = hashParts[0] & 0x7F

	number := toUint32(hashParts)

	// size to 6 digits
	// one million is the first number with 7 digits so the remainder
	// of the division will always return < 7 digits
	pwd := number % 1000000

	return pwd
}

// all []byte in this program are treated as Big Endian
func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "must specify key to use")
		os.Exit(1)
	}

	input := os.Args[1]

	// decode the key from the first argument
	inputNoSpaces := strings.Replace(input, " ", "", -1)
	inputNoSpacesUpper := strings.ToUpper(inputNoSpaces)
	key, err := base32.StdEncoding.DecodeString(inputNoSpacesUpper)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	// generate a one-time password using the time at 30-second intervals
	epochSeconds := time.Now().Unix()
	pwd := oneTimePassword(key, toBytes(epochSeconds/30))

	secondsRemaining := 30 - (epochSeconds % 30)
	fmt.Printf("%06d (%d second(s) remaining)\n", pwd, secondsRemaining)
}
<commit_msg>Add padding before base32 decoding<commit_after>package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base32"
	"fmt"
	"os"
	"strings"
	"time"
)

func toBytes(value int64) []byte {
	var result []byte
	mask := int64(0xFF)
	shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
	for _, shift := range shifts {
		result = append(result, byte((value>>shift)&mask))
	}
	return result
}

func toUint32(bytes []byte) uint32 {
	return (uint32(bytes[0]) << 24) + (uint32(bytes[1]) << 16) +
		(uint32(bytes[2]) << 8) + uint32(bytes[3])
}

func oneTimePassword(key []byte, value []byte) uint32 {
	// sign the value using HMAC-SHA1
	hmacSha1 := hmac.New(sha1.New, key)
	hmacSha1.Write(value)
	hash := hmacSha1.Sum(nil)

	// We're going to use a subset of the generated hash.
	// Using the last nibble (half-byte) to choose the index to start from.
	// This number is always appropriate as it's maximum decimal 15, the hash will
	// have the maximum index 19 (20 bytes of SHA1) and we need 4 bytes.
	offset := hash[len(hash)-1] & 0x0F

	// get a 32-bit (4-byte) chunk from the hash starting at offset
	hashParts := hash[offset : offset+4]

	// ignore the most significant bit as per RFC 4226
	hashParts[0] = hashParts[0] & 0x7F

	number := toUint32(hashParts)

	// size to 6 digits
	// one million is the first number with 7 digits so the remainder
	// of the division will always return < 7 digits
	pwd := number % 1000000

	return pwd
}

// all []byte in this program are treated as Big Endian
func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "must specify key to use")
		os.Exit(1)
	}

	input := os.Args[1]

	// decode the key from the first argument
	inputNoSpaces := strings.Replace(input, " ", "", -1)
	inputNoSpacesUpper := strings.ToUpper(inputNoSpaces)
	key, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(inputNoSpacesUpper)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	// generate a one-time password using the time at 30-second intervals
	epochSeconds := time.Now().Unix()
	pwd := oneTimePassword(key, toBytes(epochSeconds/30))

	secondsRemaining := 30 - (epochSeconds % 30)
	fmt.Printf("%06d (%d second(s) remaining)\n", pwd, secondsRemaining)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"strings"

	"github.com/alphagov/govuk_crawler_worker/http_crawler"
	"github.com/alphagov/govuk_crawler_worker/queue"
	"github.com/alphagov/govuk_crawler_worker/ttl_hash_set"
	"github.com/alphagov/govuk_crawler_worker/util"
)

var (
	amqpAddr       = util.GetEnvDefault("AMQP_ADDRESS", "amqp://guest:guest@localhost:5672/")
	exchangeName   = util.GetEnvDefault("AMQP_EXCHANGE", "govuk_crawler_exchange")
	queueName      = util.GetEnvDefault("AMQP_MESSAGE_QUEUE", "govuk_crawler_queue")
	redisAddr      = util.GetEnvDefault("REDIS_ADDRESS", "127.0.0.1:6379")
	redisKeyPrefix = util.GetEnvDefault("REDIS_KEY_PREFIX", "govuk_crawler_worker")
	rootURL        = util.GetEnvDefault("ROOT_URL", "https://www.gov.uk/")
	blacklistPaths = util.GetEnvDefault("BLACKLIST_PATHS", "/search,/government/uploads")
	mirrorRoot     = os.Getenv("MIRROR_ROOT")
)

func main() {
	if os.Getenv("GOMAXPROCS") == "" {
		// Use all available cores if not otherwise specified
		runtime.GOMAXPROCS(runtime.NumCPU())
	}
	log.Println(fmt.Sprintf("using GOMAXPROCS value of %d", runtime.NumCPU()))

	ttlHashSet, err := ttl_hash_set.NewTTLHashSet(redisKeyPrefix, redisAddr)
	if err != nil {
		log.Fatal(err)
	}
	defer ttlHashSet.Close()
	log.Println("Connected to Redis service:", ttlHashSet)

	queueManager, err := queue.NewQueueManager(amqpAddr, exchangeName, queueName)
	if err != nil {
		log.Fatal(err)
	}
	defer queueManager.Close()
	log.Println("Connected to AMQP service:", queueManager)

	crawler, err := http_crawler.NewCrawler(rootURL)
	if err != nil {
		log.Fatal("Couldn't generate Crawler:", err)
	}
	log.Println("Generated crawler:", crawler)

	deliveries, err := queueManager.Consume()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Generated delivery (consumer) channel:", deliveries)

	dontQuit := make(chan int)

	var itemToAcknowledge, itemToCrawl, itemToPersist, itemToParse <-chan *CrawlerMessageItem
	itemToPublish := make(<-chan string, 100)

	itemToCrawl = ReadFromQueue(deliveries, ttlHashSet, splitPaths(blacklistPaths))
	itemToPersist = CrawlURL(itemToCrawl, crawler)
	itemToParse = WriteItemToDisk(mirrorRoot, itemToPersist)
	itemToPublish, itemToAcknowledge = ExtractURLs(itemToParse)

	go PublishURLs(ttlHashSet, queueManager, itemToPublish)
	go AcknowledgeItem(itemToAcknowledge, ttlHashSet)

	<-dontQuit
}

func splitPaths(paths string) []string {
	if !strings.Contains(paths, ",") {
		return []string{paths}
	}

	splitPaths := strings.Split(paths, ",")
	trimmedPaths := make([]string, len(splitPaths))

	for i, v := range splitPaths {
		trimmedPaths[i] = v
	}

	return trimmedPaths
}
<commit_msg>Rename channel variables to be more descriptive<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"strings"

	"github.com/alphagov/govuk_crawler_worker/http_crawler"
	"github.com/alphagov/govuk_crawler_worker/queue"
	"github.com/alphagov/govuk_crawler_worker/ttl_hash_set"
	"github.com/alphagov/govuk_crawler_worker/util"
)

var (
	amqpAddr       = util.GetEnvDefault("AMQP_ADDRESS", "amqp://guest:guest@localhost:5672/")
	exchangeName   = util.GetEnvDefault("AMQP_EXCHANGE", "govuk_crawler_exchange")
	queueName      = util.GetEnvDefault("AMQP_MESSAGE_QUEUE", "govuk_crawler_queue")
	redisAddr      = util.GetEnvDefault("REDIS_ADDRESS", "127.0.0.1:6379")
	redisKeyPrefix = util.GetEnvDefault("REDIS_KEY_PREFIX", "govuk_crawler_worker")
	rootURL        = util.GetEnvDefault("ROOT_URL", "https://www.gov.uk/")
	blacklistPaths = util.GetEnvDefault("BLACKLIST_PATHS", "/search,/government/uploads")
	mirrorRoot     = os.Getenv("MIRROR_ROOT")
)

func main() {
	if os.Getenv("GOMAXPROCS") == "" {
		// Use all available cores if not otherwise specified
		runtime.GOMAXPROCS(runtime.NumCPU())
	}
	log.Println(fmt.Sprintf("using GOMAXPROCS value of %d", runtime.NumCPU()))

	ttlHashSet, err := ttl_hash_set.NewTTLHashSet(redisKeyPrefix, redisAddr)
	if err != nil {
		log.Fatal(err)
	}
	defer ttlHashSet.Close()
	log.Println("Connected to Redis service:", ttlHashSet)

	queueManager, err := queue.NewQueueManager(amqpAddr, exchangeName, queueName)
	if err != nil {
		log.Fatal(err)
	}
	defer queueManager.Close()
	log.Println("Connected to AMQP service:", queueManager)

	crawler, err := http_crawler.NewCrawler(rootURL)
	if err != nil {
		log.Fatal("Couldn't generate Crawler:", err)
	}
	log.Println("Generated crawler:", crawler)

	deliveries, err := queueManager.Consume()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Generated delivery (consumer) channel:", deliveries)

	dontQuit := make(chan int)

	var acknowledgeChan, crawlChan, persistChan, parseChan <-chan *CrawlerMessageItem
	publishChan := make(<-chan string, 100)

	crawlChan = ReadFromQueue(deliveries, ttlHashSet, splitPaths(blacklistPaths))
	persistChan = CrawlURL(crawlChan, crawler)
	parseChan = WriteItemToDisk(mirrorRoot, persistChan)
	publishChan, acknowledgeChan = ExtractURLs(parseChan)

	go PublishURLs(ttlHashSet, queueManager, publishChan)
	go AcknowledgeItem(acknowledgeChan, ttlHashSet)

	<-dontQuit
}

func splitPaths(paths string) []string {
	if !strings.Contains(paths, ",") {
		return []string{paths}
	}

	splitPaths := strings.Split(paths, ",")
	trimmedPaths := make([]string, len(splitPaths))

	for i, v := range splitPaths {
		trimmedPaths[i] = v
	}

	return trimmedPaths
}
<|endoftext|>


<commit_before>package main;

import (
	"os"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"encoding/binary"
	"io"
	"strings"
	"time"
	"math/rand"
	"io/ioutil"
	"path/filepath"
	"encoding/json"
)

const DIRNAME = "Dank";
var sounds = make(map[string][][]byte, 0);
var images map[string]string;

var statuses = []string{
	"hidden object games",
	"Oh... Sir!",
	"Minecraft 1.0 ALPHA",
	"with your mother",
	"something",
	"something else",
	"bored",
	"dead"}

type Settings struct{
	vc *discordgo.VoiceConnection
	playing bool
	commander string
}
var settings = make(map[string]*Settings);

func main(){
	args := os.Args[1:];

	if(len(args) < 1){
		fmt.Println("No token provided!");
		return;
	}
	token := args[0];

	fmt.Println("Loading...");

	err := os.MkdirAll(DIRNAME, 0755);
	if(err != nil){
		fmt.Fprintln(os.Stderr, "I THINK THERE WAS ERROR", err);
		return;
	}
	files, err := ioutil.ReadDir(DIRNAME);
	if(err != nil){
		fmt.Fprintln(os.Stderr, "I THINK THERE WAS ERROR", err);
		return;
	}
	for _, file := range files{
		if(file.IsDir()){
			continue;
		}
		name := file.Name();
		if(!strings.HasSuffix(name, ".dca")){
			continue;
		}

		bytes := make([][]byte, 0);
		err = load(name, &bytes);
		if(err != nil){
			continue;
		}

		name = strings.ToLower(strings.TrimSuffix(name, ".dca"));
		sounds[name] = bytes;
	}

	data, err := ioutil.ReadFile("Dank/images.json");
	if(err != nil){
		fmt.Fprintln(os.Stderr, "DAT images.json FILE EZ POOF!", err);
		images = make(map[string]string, 0);
	} else {
		err = json.Unmarshal(data, &images);
		if(err != nil){
			fmt.Fprintln(os.Stderr, "DO U EVEN JSON, BRUH?", err);
			images = make(map[string]string, 0);
		}
	}

	fmt.Println("Starting...");
	d, err := discordgo.New("Bot " + token);
	if(err != nil){
		fmt.Fprintln(os.Stderr, "I THINK THERE WAS ERROR", err);
		return;
	}
	d.AddHandler(ready);
	d.AddHandler(messageCreate);
	d.AddHandler(messageUpdate);
	err = d.Open();

	if(err != nil){
		fmt.Fprintln(os.Stderr, "I THINK THERE WAS ERROR", err);
		return;
	}
	fmt.Println("Started!");

	<-make(chan struct{});
}

func load(file string, buffer *[][]byte) error{
	f, err := os.Open(filepath.Join(DIRNAME, file));
	if err != nil {
		fmt.Fprintln(os.Stderr, "FILE WAS WEIRD IDK:", err);
		return err;
	}

	var length int16;
	for {
		err := binary.Read(f, binary.LittleEndian, &length);

		if(err == io.EOF || err == io.ErrUnexpectedEOF){
			break;
		} else if(err != nil){
			fmt.Fprintln(os.Stderr, "IDK WAT U DID BUT WEL DONN NOOB,", err);
			return err;
		}

		buf := make([]byte, length);
		err = binary.Read(f, binary.LittleEndian, &buf);
		if(err != nil){
			fmt.Fprintln(os.Stderr, "IDK WAT U DID BUT WEL DONN NOOB,", err);
			return err;
		}

		*buffer = append(*buffer, buf);
	}
	return nil;
}

func play(buffer [][]byte, session *discordgo.Session, guild, channel string, s *Settings){
	s.playing = true;
	var err error;
	s.vc, err = session.ChannelVoiceJoin(guild, channel, false, true);
	if(err != nil){
		fmt.Fprintln(os.Stderr, "LEL FREGGIN NOOB,", err);
		s.playing = false;
		return;
	}

	err = s.vc.Speaking(true);
	if(err != nil){
		fmt.Fprintln(os.Stderr, "I HAS TO TYPE ALL DESE ERROR MESSAGES " +
		"HAVE SOME SYMPATHY PLS", err);
		s.playing = false;
		return;
	}

	for _, buf := range buffer {
		if s.vc == nil { return; }
		s.vc.OpusSend <- buf;
	}

	err = s.vc.Speaking(false);
	if(err != nil){
		fmt.Fprintln(os.Stderr, err);
	}
	err = s.vc.Disconnect();
	if(err != nil){
		fmt.Fprintln(os.Stderr, err);
	}
	s.playing = false;
}

func messageCreate(session *discordgo.Session, event *discordgo.MessageCreate){
	message(session, event.Message)
}
func messageUpdate(session *discordgo.Session, event *discordgo.MessageUpdate){
	message(session, event.Message)
}
func message(session *discordgo.Session, event *discordgo.Message){
	msg := strings.ToLower(strings.TrimSpace(event.Content));
	author := event.Author;

	channel, err := session.State.Channel(event.ChannelID);
	if(err != nil){ fmt.Fprintln(os.Stderr, err); return; }

	guild, err := session.State.Guild(channel.GuildID);
	if(err != nil){ fmt.Fprintln(os.Stderr, err); return; }

	s := settings[guild.ID];
	if(s == nil){
		s = &Settings{};
		settings[guild.ID] = s;
	}

	if(s.commander != "" && s.commander != author.ID){
		return;
	}

	buffer, ok := sounds[msg];
	if(ok){
		if(!s.playing){
			for _, state := range guild.VoiceStates{
				if state.UserID == event.Author.ID{
					go react(session, event);
					play(buffer, session, guild.ID, state.ChannelID, s);
					return;
				}
			}
		}
		return;
	}

	for keyword, url := range images{
		if(strings.Contains(msg, strings.ToLower(keyword))){
			go react(session, event);
			_, err = session.ChannelMessageSendEmbed(event.ChannelID,
				&discordgo.MessageEmbed{
					Image: &discordgo.MessageEmbedImage{
						URL: url,
					},
				});
			return;
		}
	}

	switch(msg){
		case "thx":
			if(s.vc != nil && s.playing){
				err := s.vc.Speaking(false);
				if(err != nil){ fmt.Fprintln(os.Stderr, err); }

				err = s.vc.Disconnect();
				if(err != nil){ fmt.Fprintln(os.Stderr, err); }

				s.playing = false;
			}
		case "listen only to me plz":
			s.commander = author.ID;
		case "every1 owns u stopad robot":
			s.commander = "";
	}
}

func ready(session *discordgo.Session, event *discordgo.Ready){
	c := time.Tick(time.Second * 5);

	for _ = range c{
		err := session.UpdateStatus(0, statuses[rand.Intn(len(statuses))]);
		if(err != nil){ fmt.Fprintln(os.Stderr, err); return; }
	}
}

func react(session *discordgo.Session, event *discordgo.Message){
	err := session.MessageReactionAdd(event.ChannelID, event.ID, "👌");
	if(err != nil){
		fmt.Fprintln(os.Stderr, "Couldn't react,", err);
		return;
	}
	err = session.MessageReactionAdd(event.ChannelID, event.ID, "😂");
	if(err != nil){
		fmt.Fprintln(os.Stderr, "Couldn't react,", err);
	}
}
<commit_msg>ERROR STACK TREYS<commit_after>package main;

import (
	"os"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"encoding/binary"
	"io"
	"strings"
	"time"
	"math/rand"
	"io/ioutil"
	"path/filepath"
	"encoding/json"
	"runtime/debug"
)

const DIRNAME = "Dank";
var sounds = make(map[string][][]byte, 0);
var images map[string]string;

var statuses = []string{
	"hidden object games",
	"Oh... Sir!",
	"Minecraft 1.0 ALPHA",
	"with your mother",
	"something",
	"something else",
	"bored",
	"dead"}

type Settings struct{
	vc *discordgo.VoiceConnection
	playing bool
	commander string
}
var settings = make(map[string]*Settings);

func main(){
	args := os.Args[1:];

	if(len(args) < 1){
		fmt.Println("No token provided!");
		return;
	}
	token := args[0];

	fmt.Println("Loading...");

	err := os.MkdirAll(DIRNAME, 0755);
	if(err != nil){
		printErr(err);
		return;
	}
	files, err := ioutil.ReadDir(DIRNAME);
	if(err != nil){
		printErr(err);
		return;
	}
	for _, file := range files{
		if(file.IsDir()){
			continue;
		}
		name := file.Name();
		if(!strings.HasSuffix(name, ".dca")){
			continue;
		}

		bytes := make([][]byte, 0);
		err = load(name, &bytes);
		if(err != nil){
			continue;
		}

		name = strings.ToLower(strings.TrimSuffix(name, ".dca"));
		sounds[name] = bytes;
	}

	data, err := ioutil.ReadFile("Dank/images.json");
	if(err != nil){
		printErr(err);
		images = make(map[string]string, 0);
	} else {
		err = json.Unmarshal(data, &images);
		if(err != nil){
			printErr(err);
			images = make(map[string]string, 0);
		}
	}

	fmt.Println("Starting...");
	d, err := discordgo.New("Bot " + token);
	if(err != nil){
		printErr(err);
		return;
	}
	d.AddHandler(ready);
	d.AddHandler(messageCreate);
	d.AddHandler(messageUpdate);
	err = d.Open();

	if(err != nil){
		printErr(err);
		return;
	}
	fmt.Println("Started!");

	<-make(chan struct{});
}

func load(file string, buffer *[][]byte) error{
	f, err := os.Open(filepath.Join(DIRNAME, file));
	if err != nil {
		printErr(err);
		return err;
	}

	var length int16;
	for {
		err := binary.Read(f, binary.LittleEndian, &length);

		if(err == io.EOF || err == io.ErrUnexpectedEOF){
			break;
		} else if(err != nil){
			printErr(err);
			return err;
		}

		buf := make([]byte, length);
		err = binary.Read(f, binary.LittleEndian, &buf);
		if(err != nil){
			printErr(err);
			return err;
		}

		*buffer = append(*buffer, buf);
	}
	return nil;
}

func play(buffer [][]byte, session *discordgo.Session, guild, channel string, s *Settings){
	s.playing = true;
	var err error;
	s.vc, err = session.ChannelVoiceJoin(guild, channel, false, true);
	if(err != nil){
		printErr(err);
		s.playing = false;
		return;
	}

	err = s.vc.Speaking(true);
	if(err != nil){
		printErr(err);
		s.playing = false;
		return;
	}

	for _, buf := range buffer {
		if s.vc == nil { return; }
		s.vc.OpusSend <- buf;
	}

	err = s.vc.Speaking(false);
	if(err != nil){
		printErr(err);
	}
	err = s.vc.Disconnect();
	if(err != nil){
		printErr(err);
	}
	s.playing = false;
}

func messageCreate(session *discordgo.Session, event *discordgo.MessageCreate){
	message(session, event.Message)
}
func messageUpdate(session *discordgo.Session, event *discordgo.MessageUpdate){
	message(session, event.Message)
}
func message(session *discordgo.Session, event *discordgo.Message){
	msg := strings.ToLower(strings.TrimSpace(event.Content));
	author := event.Author;

	channel, err := session.State.Channel(event.ChannelID);
	if(err != nil){ printErr(err); return; }

	if(channel.IsPrivate){
		return;
	}

	guild, err := session.State.Guild(channel.GuildID);
	if(err != nil){ printErr(err); return; }

	s := settings[guild.ID];
	if(s == nil){
		s = &Settings{};
		settings[guild.ID] = s;
	}

	if(s.commander != "" && s.commander != author.ID){
		return;
	}

	buffer, ok := sounds[msg];
	if(ok){
		if(!s.playing){
			for _, state := range guild.VoiceStates{
				if state.UserID == event.Author.ID{
					go react(session, event);
					play(buffer, session, guild.ID, state.ChannelID, s);
					return;
				}
			}
		}
		return;
	}

	for keyword, url := range images{
		if(strings.Contains(msg, strings.ToLower(keyword))){
			go react(session, event);
			_, err = session.ChannelMessageSendEmbed(event.ChannelID,
				&discordgo.MessageEmbed{
					Image: &discordgo.MessageEmbedImage{
						URL: url,
					},
				});
			return;
		}
	}

	switch(msg){
		case "thx":
			if(s.vc != nil && s.playing){
				err := s.vc.Speaking(false);
				if(err != nil){ printErr(err); }

				err = s.vc.Disconnect();
				if(err != nil){ printErr(err); }

				s.playing = false;
			}
		case "listen only to me plz":
			s.commander = author.ID;
		case "every1 owns u stopad robot":
			s.commander = "";
	}
}

func ready(session *discordgo.Session, event *discordgo.Ready){
	c := time.Tick(time.Second * 5);

	for _ = range c{
		err := session.UpdateStatus(0, statuses[rand.Intn(len(statuses))]);
		if(err != nil){ printErr(err); return; }
	}
}

func react(session *discordgo.Session, event *discordgo.Message){
	err := session.MessageReactionAdd(event.ChannelID, event.ID, "👌");
	if(err != nil){
		printErr(err);
		return;
	}
	err = session.MessageReactionAdd(event.ChannelID, event.ID, "😂");
	if(err != nil){
		printErr(err);
	}
}

func printErr(err error){
	fmt.Fprintln(os.Stderr, "Error:", err);
	debug.PrintStack();
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"os"
	"strconv"
)

func main() {
	file, err := os.Open("sudoku.csv")
	if err != nil {
		log.Fatal(err)
	}
	csvReader := csv.NewReader(file)
	gridStr, err := csvReader.ReadAll()
	if err != nil {
		log.Fatal(err)
	}
	grid := make([][]int, 9)
	for i := 0; i < 9; i++ {
		grid[i] = make([]int, 9)
		for j := 0; j < 9; j++ {
			if len(gridStr[i][j]) > 0 {
				num, err := strconv.ParseInt(gridStr[i][j], 10, 64)
				if err != nil {
					log.Fatal("Error parsing csv file.", err)
				}
				grid[i][j] = int(num)
			} else {
				grid[i][j] = 0 // this isn't really necessary since the 0 value of an int is 0
			}
		}
	}
	PrintGrid(grid)
}

func PrintGrid(grid [][]int) {
	for i, hLine := range grid {
		if i%3 == 0 {
			fmt.Println("  -------------------------- ")
		}
		for j, num := range hLine {
			if j%3 == 0 {
				fmt.Print(" | ")
			}
			fmt.Printf(" %d", num)
			if j == 8 {
				fmt.Print(" |\n")
			}
		}
	}
	fmt.Println("  -------------------------- ")
}
<commit_msg>Changed grid from slice to array. Added comments to functions. Added the GetBox function. Added the FindPosibleSolutions function.<commit_after>package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"os"
	"strconv"
)

func main() {
	file, err := os.Open("sudoku.csv")
	if err != nil {
		log.Fatal(err)
	}
	csvReader := csv.NewReader(file)
	gridStr, err := csvReader.ReadAll()
	if err != nil {
		log.Fatal(err)
	}
	var grid [9][9]int
	for i := 0; i < 9; i++ {
		grid[i] = [9]int{}
		for j := 0; j < 9; j++ {
			if len(gridStr[i][j]) > 0 {
				num, err := strconv.ParseInt(gridStr[i][j], 10, 64)
				if err != nil {
					log.Fatal("Error parsing csv file.", err)
				}
				grid[i][j] = int(num)
			} else {
				grid[i][j] = 0 // this isn't really necessary since the 0 value of an int is 0
			}
		}
	}
	PrintGrid(grid)
	for x := 0; x < 9; x++ {
		for y := 0; y < 9; y++ {
			posibleSolutions := FindPosibleSolutions(x, y, grid)
			if len(posibleSolutions) == 1 {
				fmt.Printf("Definitive solution for (%d, %d): %v\n", x, y, posibleSolutions)
			}
		}
	}
}

// PrintGrid prints the complete Sudoku grid.
func PrintGrid(grid [9][9]int) {
	for i, hLine := range grid {
		if i%3 == 0 {
			fmt.Println("  -------------------------- ")
		}
		for j, num := range hLine {
			if j%3 == 0 {
				fmt.Print(" | ")
			}
			fmt.Printf(" %d", num)
			if j == 8 {
				fmt.Print(" |\n")
			}
		}
	}
	fmt.Println("  -------------------------- ")
}

// GetBox takes a position and a grid and returns the box that position belongs to.
// Each position having their respective value.
func GetBox(x, y int, grid [9][9]int) [3][3]int {
	var box [3][3]int
	x -= x % 3
	y -= y % 3
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			box[i][j] = grid[x+i][y+j]
		}
	}
	return box
}

// FindPosibleSolutions calculates the posible solutions for a single position in the grid.
//
// If the position already has a value, then this function returns an empty slice.
func FindPosibleSolutions(x, y int, grid [9][9]int) []int {
	// if the position is already filled, there's no need to find any other solution
	if grid[x][y] != 0 {
		return []int{}
	}
	// start with all posible solutions
	posibleSolutions := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

	// find numbers in the same line (either vertical or horizontal)
	for i := 0; i < 9; i++ {

		// horizontal line check
		if grid[x][i] != 0 {
			// remove from posibleSolutions slice
			for index, element := range posibleSolutions {
				if element == grid[x][i] {
					posibleSolutions = append(posibleSolutions[:index], posibleSolutions[index+1:]...)
					break
				}
			}
		}

		// vertical line check
		if grid[i][y] != 0 {
			// remove from posibleSolutions slice
			for index, element := range posibleSolutions {
				if element == grid[i][y] {
					posibleSolutions = append(posibleSolutions[:index], posibleSolutions[index+1:]...)
					break
				}
			}
		}
	}
	// find numbers in the same box
	boxX := x - (x % 3)
	boxY := y - (y % 3)
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			elem := grid[boxX+i][boxY+j]
			for i := range posibleSolutions {
				if posibleSolutions[i] == elem {
					posibleSolutions = append(posibleSolutions[:i], posibleSolutions[i+1:]...)
					break
				}
			}
		}
	}
	return posibleSolutions
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/josledp/goprompt/prompt"
)

var logger *log.Logger

func main() {
	var noColor bool
	var template string
	var customTemplate string

	config, err := prompt.NewConfigFromFile(os.Getenv("HOME") + "/.config/goprompt/goprompt.json")
	if err != nil {
		log.Fatalf("unable to get config: %v", err)
	}

	currentTemplates := strings.Join(prompt.GetDefaultTemplates(), ",")
	flag.StringVar(&template, "template", "Evermeet", "template to use for the prompt ("+currentTemplates+")")
	flag.StringVar(&customTemplate, "custom-template", "<(%python%) ><%aws%|><%user% ><%lastcommand% ><%path%>< %git%>$ ", "template to use for the prompt")
	flag.BoolVar(&noColor, "no-color", false, "Disable color on prompt")

	flag.Parse()

	flagsSet := make(map[string]struct{})
	flag.Visit(func(f *flag.Flag) { flagsSet[f.Name] = struct{}{} })

	_, templateSet := flagsSet["template"]
	_, customTemplateSet := flagsSet["custom-template"]

	if templateSet && customTemplateSet {
		fmt.Fprintf(os.Stderr, "Please provice --template or --custom-template, but not both!")
		os.Exit(1)
	}

	var t string
	var options map[string]interface{}
	options, _ = config.GetOptions()

	if customTemplateSet {
		t = customTemplate
	} else if !templateSet {
		t, _ = config.GetCustomTemplate()
	}

	if t == "" {
		var ok bool
		t, ok = prompt.GetTemplate(template)
		if !ok {
			fmt.Fprintf(os.Stderr, "Template %s not found", template)
		}
		if options == nil {
			options, _ = prompt.GetTemplateOptions(template)
		}
	}
	pr := prompt.New(options)
	output := pr.Compile(t, !noColor)
	fmt.Println(output)

}
<commit_msg>add enableCPUProf funcion (without actually using it, but for the record...<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/pprof"
	"strings"

	"github.com/josledp/goprompt/prompt"
)

var logger *log.Logger

//enableCPUProf call me this way if you want CPU Profiling:
// defer enableCPUProf()()
func enableCPUProf() func() {

	f, err := os.Create("/tmp/cpu.prof")
	if err != nil {
		log.Fatal(err)
	}
	pprof.StartCPUProfile(f)
	return pprof.StopCPUProfile
}

func main() {
	var noColor bool
	var template string
	var customTemplate string

	config, err := prompt.NewConfigFromFile(os.Getenv("HOME") + "/.config/goprompt/goprompt.json")
	if err != nil {
		log.Fatalf("unable to get config: %v", err)
	}

	currentTemplates := strings.Join(prompt.GetDefaultTemplates(), ",")
	flag.StringVar(&template, "template", "Evermeet", "template to use for the prompt ("+currentTemplates+")")
	flag.StringVar(&customTemplate, "custom-template", "<(%python%) ><%aws%|><%user% ><%lastcommand% ><%path%>< %git%>$ ", "template to use for the prompt")
	flag.BoolVar(&noColor, "no-color", false, "Disable color on prompt")

	flag.Parse()

	flagsSet := make(map[string]struct{})
	flag.Visit(func(f *flag.Flag) { flagsSet[f.Name] = struct{}{} })

	_, templateSet := flagsSet["template"]
	_, customTemplateSet := flagsSet["custom-template"]

	if templateSet && customTemplateSet {
		fmt.Fprintf(os.Stderr, "Please provice --template or --custom-template, but not both!")
		os.Exit(1)
	}

	var t string
	var options map[string]interface{}
	options, _ = config.GetOptions()

	if customTemplateSet {
		t = customTemplate
	} else if !templateSet {
		t, _ = config.GetCustomTemplate()
	}

	if t == "" {
		var ok bool
		t, ok = prompt.GetTemplate(template)
		if !ok {
			fmt.Fprintf(os.Stderr, "Template %s not found", template)
		}
		if options == nil {
			options, _ = prompt.GetTemplateOptions(template)
		}
	}
	pr := prompt.New(options)
	output := pr.Compile(t, !noColor)
	fmt.Println(output)

}
<|endoftext|>