<commit_before>package main

import (
	"log"
	"os"
	"strconv"

	"github.com/codegangsta/cli"
	"github.com/therealbill/libredis/client"
	"github.com/therealbill/libredis/structures"
)

var (
	app           *cli.App
	sentinel_list cli.StringSlice
)

func main() {
	app = cli.NewApp()
	app.Name = "correct-pod-configs"
	app.Usage = "Correct all pods' down-after-millisecond value in a given constellation"
	app.Version = "1"
	app.EnableBashCompletion = true
	author := cli.Author{Name: "Bill Anderson", Email: "bill.anderson@rackspace.com"}
	app.Authors = append(app.Authors, author)
	sentinel_list = cli.StringSlice{}
	app.Flags = []cli.Flag{
		cli.StringSliceFlag{
			Name:  "sentinels,s",
			Usage: "Addresses of the sentinel nodes",
			Value: &sentinel_list,
		},
		cli.StringFlag{
			Name:   "targetvalue,t",
			Usage:  "The value to set down-after-milliseconds to",
			Value:  "3000",
			EnvVar: "CD_TARGET",
		},
		cli.IntFlag{
			Name:   "ignore,i",
			Usage:  "Skip over pods with this s their down-after-milliseconds value",
			Value:  345600000,
			EnvVar: "CD_IGNORE",
		},
		cli.BoolFlag{
			Name:  "commit,c",
			Usage: "If enabled, will actually commit the change in Sentinel. Default is off for checking.",
		},
		cli.BoolFlag{
			Name:  "all,a",
			Usage: "If enabled with -c will the change to ALL pods in the constellation",
		},
		cli.BoolFlag{
			Name:  "verbose,d",
			Usage: "Be a bit more chatty",
		},
	}
	app.Action = setTimeout
	app.Run(os.Args)

}

func setTimeout(c *cli.Context) {
	sentinels := c.StringSlice("sentinels")
	if len(sentinels) == 0 {
		log.Fatal("Need a list of Sentinel addresses")
	}
	target := c.String("targetvalue")
	if target == "" {
		log.Fatal("Need a value to set them to there, Hoss.")
	}
	for _, s := range sentinels {
		spods, conn, err := getPodListFromSentinel(s)
		if err != nil {
			log.Printf("Skipping sentinel %s", s)
			continue
		}
		defaults := 0
		corrects := 0
		others := 0
		ignores := 0
		itarget, _ := strconv.Atoi(target)
		for _, pod := range spods {
			if c.Bool("all") {
				if pod.DownAfterMilliseconds == itarget {
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s is correct, skipping.", s, pod.Name)
					}
					corrects++
				} else {
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s is incorrect.", s, pod.Name)
					}
					others++
					if c.Bool("commit") {
						log.Printf("[%s] Updating pod %s to %s from %d", s, pod.Name, target, pod.DownAfterMilliseconds)
						_ = conn.SentinelSetString(pod.Name, "down-after-milliseconds", target)
					}
				}
			} else {
				switch pod.DownAfterMilliseconds {
				case itarget:
					corrects++
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s is correct", s, pod.Name)
					}
				case 30000:
					defaults++
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s has Redis default", s, pod.Name)
					}
					if c.Bool("commit") {
						log.Printf("[%s] Updating pod %s to %s from default", s, pod.Name, target)
						_ = conn.SentinelSetString(pod.Name, "down-after-milliseconds", target)
					}
				case c.Int("ignore"):
					ignores++
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s has ignores value", s, pod.Name)
					}
				default:
					others++
					log.Printf("[%s] Pod %s has invalid value %d", s, pod.Name, pod.DownAfterMilliseconds)
				}
			}
		}
		log.Printf("[%s] Correct: %d Default: %d Resizes: %d Other: %d", s, corrects, defaults, ignores, others)
	}

}

func getPodListFromSentinel(ip string) (pods []structures.MasterInfo, conn *client.Redis, err error) {
	conn, err = client.Dial(ip, 26379)
	if err != nil {
		log.Printf("Unable to connect to %s. Error='%v'", ip, err)
		return
	}
	pods, err = conn.SentinelMasters()
	return
}
<commit_msg>version bump<commit_after>package main

import (
	"log"
	"os"
	"strconv"

	"github.com/codegangsta/cli"
	"github.com/therealbill/libredis/client"
	"github.com/therealbill/libredis/structures"
)

var (
	app           *cli.App
	sentinel_list cli.StringSlice
)

func main() {
	app = cli.NewApp()
	app.Name = "correct-pod-configs"
	app.Usage = "Correct all pods' down-after-millisecond value in a given constellation"
	app.Version = "1.1"
	app.EnableBashCompletion = true
	author := cli.Author{Name: "Bill Anderson", Email: "bill.anderson@rackspace.com"}
	app.Authors = append(app.Authors, author)
	sentinel_list = cli.StringSlice{}
	app.Flags = []cli.Flag{
		cli.StringSliceFlag{
			Name:  "sentinels,s",
			Usage: "Addresses of the sentinel nodes",
			Value: &sentinel_list,
		},
		cli.StringFlag{
			Name:   "targetvalue,t",
			Usage:  "The value to set down-after-milliseconds to",
			Value:  "3000",
			EnvVar: "CD_TARGET",
		},
		cli.IntFlag{
			Name:   "ignore,i",
			Usage:  "Skip over pods with this s their down-after-milliseconds value",
			Value:  345600000,
			EnvVar: "CD_IGNORE",
		},
		cli.BoolFlag{
			Name:  "commit,c",
			Usage: "If enabled, will actually commit the change in Sentinel. Default is off for checking.",
		},
		cli.BoolFlag{
			Name:  "all,a",
			Usage: "If enabled with -c will the change to ALL pods in the constellation",
		},
		cli.BoolFlag{
			Name:  "verbose,d",
			Usage: "Be a bit more chatty",
		},
	}
	app.Action = setTimeout
	app.Run(os.Args)

}

func setTimeout(c *cli.Context) {
	sentinels := c.StringSlice("sentinels")
	if len(sentinels) == 0 {
		log.Fatal("Need a list of Sentinel addresses")
	}
	target := c.String("targetvalue")
	if target == "" {
		log.Fatal("Need a value to set them to there, Hoss.")
	}
	for _, s := range sentinels {
		spods, conn, err := getPodListFromSentinel(s)
		if err != nil {
			log.Printf("Skipping sentinel %s", s)
			continue
		}
		defaults := 0
		corrects := 0
		others := 0
		ignores := 0
		itarget, _ := strconv.Atoi(target)
		for _, pod := range spods {
			if c.Bool("all") {
				if pod.DownAfterMilliseconds == itarget {
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s is correct, skipping.", s, pod.Name)
					}
					corrects++
				} else {
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s is incorrect.", s, pod.Name)
					}
					others++
					if c.Bool("commit") {
						log.Printf("[%s] Updating pod %s to %s from %d", s, pod.Name, target, pod.DownAfterMilliseconds)
						_ = conn.SentinelSetString(pod.Name, "down-after-milliseconds", target)
					}
				}
			} else {
				switch pod.DownAfterMilliseconds {
				case itarget:
					corrects++
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s is correct", s, pod.Name)
					}
				case 30000:
					defaults++
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s has Redis default", s, pod.Name)
					}
					if c.Bool("commit") {
						log.Printf("[%s] Updating pod %s to %s from default", s, pod.Name, target)
						_ = conn.SentinelSetString(pod.Name, "down-after-milliseconds", target)
					}
				case c.Int("ignore"):
					ignores++
					if c.Bool("verbose") {
						log.Printf("[%s] Pod %s has ignores value", s, pod.Name)
					}
				default:
					others++
					log.Printf("[%s] Pod %s has invalid value %d", s, pod.Name, pod.DownAfterMilliseconds)
				}
			}
		}
		log.Printf("[%s] Correct: %d Default: %d Resizes: %d Other: %d", s, corrects, defaults, ignores, others)
	}

}

func getPodListFromSentinel(ip string) (pods []structures.MasterInfo, conn *client.Redis, err error) {
	conn, err = client.Dial(ip, 26379)
	if err != nil {
		log.Printf("Unable to connect to %s. Error='%v'", ip, err)
		return
	}
	pods, err = conn.SentinelMasters()
	return
}
<|endoftext|>


<commit_before>package main

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

	"github.com/rightscale/rsc/cmd"
	"gopkg.in/alecthomas/kingpin.v1"

	// phoney reference to make Godep pull this in for the code generators
	_ "bitbucket.org/pkg/inflect"
)

// Command line client entry point.
func main() {
	app := kingpin.New("rsc", "A RightScale API client")
	app.Version(VV)

	cmdLine, err := ParseCommandLine(app)
	if err != nil {
		PrintFatal(err.Error())
	}

	// Execute appropriate command
	var resp *http.Response
	topCommand := strings.Split(cmdLine.Command, " ")[0]
	if topCommand == "setup" {
		err = CreateConfig(cmdLine.ConfigPath)
	} else {
		var client cmd.CommandClient
		client, err = ApiClient(topCommand, cmdLine)
		if err == nil {
			resp, err = runCommand(client, cmdLine)
		}
	}

	// Handle command results
	if err != nil {
		PrintFatal(err.Error())
	}
	if resp == nil {
		return // No results, just exit (e.g. printed help)
	}

	// Let user know if something went wrong before doing any other processing
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		fmt.Fprintf(os.Stderr, "%d: %s\n", resp.StatusCode, http.StatusText(resp.StatusCode))
	}

	// Handle command output (apply any extraction)
	displayer, err := NewDisplayer(resp)
	if err != nil {
		PrintFatal(err.Error())
	}
	notExactlyOneError := false
	if cmdLine.ExtractOneSelect != "" {
		err = displayer.ApplySingleExtract(cmdLine.ExtractOneSelect)
		if err != nil {
			notExactlyOneError = strings.Contains(err.Error(),
				"instead of one value") // Ugh, there has to be a better way
		}
	} else if cmdLine.ExtractSelector != "" {
		err = displayer.ApplyExtract(cmdLine.ExtractSelector, false)
	} else if cmdLine.ExtractSelectorJson != "" {
		err = displayer.ApplyExtract(cmdLine.ExtractSelectorJson, true)
	} else if cmdLine.ExtractHeader != "" {
		err = displayer.ApplyHeaderExtract(cmdLine.ExtractHeader)
	}
	if err != nil {
		PrintFatal(err.Error())
	}
	if cmdLine.Pretty {
		displayer.Pretty()
	}

	// We're done, print output and figure out correct exit code
	fmt.Fprint(out, displayer.Output())
	exitStatus := 0
	switch {
	case notExactlyOneError:
		exitStatus = 6
	case resp.StatusCode == 401:
		exitStatus = 1
	case resp.StatusCode == 403:
		exitStatus = 3
	case resp.StatusCode == 404:
		exitStatus = 4
	case resp.StatusCode > 399 && resp.StatusCode < 500:
		exitStatus = 2
	case resp.StatusCode > 499:
		exitStatus = 5
	}
	osExit(exitStatus)
}

// Helper that runs command line with give command client
func runCommand(client cmd.CommandClient, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	cmds := strings.Split(cmdLine.Command, " ")
	if cmdLine.ShowHelp {
		err = client.ShowCommandHelp(cmdLine.Command)
	} else if len(cmds) > 1 && cmds[1] == "actions" {
		err = client.ShowApiActions(cmdLine.Command)
	} else {
		resp, err = client.RunCommand(cmdLine.Command)
	}
	return
}
<commit_msg>Do not apply extraction when request fails.<commit_after>package main

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

	"github.com/rightscale/rsc/cmd"
	"gopkg.in/alecthomas/kingpin.v1"

	// phoney reference to make Godep pull this in for the code generators
	_ "bitbucket.org/pkg/inflect"
)

// Command line client entry point.
func main() {
	app := kingpin.New("rsc", "A RightScale API client")
	app.Version(VV)

	cmdLine, err := ParseCommandLine(app)
	if err != nil {
		PrintFatal(err.Error())
	}

	// Execute appropriate command
	var resp *http.Response
	topCommand := strings.Split(cmdLine.Command, " ")[0]
	if topCommand == "setup" {
		err = CreateConfig(cmdLine.ConfigPath)
	} else {
		var client cmd.CommandClient
		client, err = ApiClient(topCommand, cmdLine)
		if err == nil {
			resp, err = runCommand(client, cmdLine)
		}
	}

	// Handle command results
	if err != nil {
		PrintFatal(err.Error())
	}
	if resp == nil {
		return // No results, just exit (e.g. printed help)
	}

	var notExactlyOneError bool
	displayer, err := NewDisplayer(resp)
	if err != nil {
		PrintFatal(err.Error())
	}
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		// Let user know if something went wrong
		fmt.Fprintf(os.Stderr, "%s\n", resp.Status)
		if len(displayer.body) > 0 {
			fmt.Println(displayer.body)
		}
	} else {
		// Handle command output (apply any extraction)
		if cmdLine.ExtractOneSelect != "" {
			err = displayer.ApplySingleExtract(cmdLine.ExtractOneSelect)
			if err != nil {
				notExactlyOneError = strings.Contains(err.Error(),
					"instead of one value") // Ugh, there has to be a better way
			}
		} else if cmdLine.ExtractSelector != "" {
			err = displayer.ApplyExtract(cmdLine.ExtractSelector, false)
		} else if cmdLine.ExtractSelectorJson != "" {
			err = displayer.ApplyExtract(cmdLine.ExtractSelectorJson, true)
		} else if cmdLine.ExtractHeader != "" {
			err = displayer.ApplyHeaderExtract(cmdLine.ExtractHeader)
		}
		if err != nil {
			PrintFatal(err.Error())
		}
		if cmdLine.Pretty {
			displayer.Pretty()
		}

		// We're done, print output and figure out correct exit code
		fmt.Fprint(out, displayer.Output())
	}
	exitStatus := 0
	switch {
	case notExactlyOneError:
		exitStatus = 6
	case resp.StatusCode == 401:
		exitStatus = 1
	case resp.StatusCode == 403:
		exitStatus = 3
	case resp.StatusCode == 404:
		exitStatus = 4
	case resp.StatusCode > 399 && resp.StatusCode < 500:
		exitStatus = 2
	case resp.StatusCode > 499:
		exitStatus = 5
	}
	osExit(exitStatus)
}

// Helper that runs command line with give command client
func runCommand(client cmd.CommandClient, cmdLine *cmd.CommandLine) (resp *http.Response, err error) {
	cmds := strings.Split(cmdLine.Command, " ")
	if cmdLine.ShowHelp {
		err = client.ShowCommandHelp(cmdLine.Command)
	} else if len(cmds) > 1 && cmds[1] == "actions" {
		err = client.ShowApiActions(cmdLine.Command)
	} else {
		resp, err = client.RunCommand(cmdLine.Command)
	}
	return
}
<|endoftext|>


<commit_before>package pcpeer

import "github.com/tinzenite/core"

func main() {
	// just run core for now
	core.Run()
}
<commit_msg>package name<commit_after>package main

import "github.com/tinzenite/core"

func main() {
	// just run core for now
	core.Run()
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Home Office All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package main

import (
	"os"
	"os/signal"
	"syscall"

	"github.com/golang/glog"
)

const (
	Prog    = "vault-sidekick"
	Version = "0.0.1"
)

func main() {
	var err error
	var vault *VaultService

	// step: parse and validate the command line / environment options
	if err = parseOptions(); err != nil {
		showUsage("invalid options, %s", err)
	}

	glog.Infof("starting the %s, version: %s", Prog, Version)

	// step: create a client to vault
	if vault, err = NewVaultService(options.vaultURL); err != nil {
		showUsage("unable to create the vault client: %s", err)
	}

	// step: setup the termination signals
	signalChannel := make(chan os.Signal)
	signal.Notify(signalChannel, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

	// step: create a channel to receive events upon and add our resources for renewal
	updates := make(chan VaultEvent, 10)
	vault.AddListener(updates)

	// step: add each of the resources to the service processor
	for _, rn := range options.resources.items {
		if err := rn.IsValid(); err != nil {
			showUsage("%s", err)
		}
		vault.Watch(rn)
	}

	// step: we simply wait for events i.e. secrets from vault and write them to the output directory
	for {
		select {
		case evt := <-updates:
			go writeResource(evt.Resource, evt.Secret)

		case <-signalChannel:
			glog.Infof("recieved a termination signal, shutting down the service")
			os.Exit(0)
		}
	}
}
<commit_msg>- pushing the version to v1.0.2<commit_after>/*
Copyright 2015 Home Office All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package main

import (
	"os"
	"os/signal"
	"syscall"

	"github.com/golang/glog"
)

const (
	Prog    = "vault-sidekick"
	Version = "0.0.2"
)

func main() {
	var err error
	var vault *VaultService

	// step: parse and validate the command line / environment options
	if err = parseOptions(); err != nil {
		showUsage("invalid options, %s", err)
	}

	glog.Infof("starting the %s, version: %s", Prog, Version)

	// step: create a client to vault
	if vault, err = NewVaultService(options.vaultURL); err != nil {
		showUsage("unable to create the vault client: %s", err)
	}

	// step: setup the termination signals
	signalChannel := make(chan os.Signal)
	signal.Notify(signalChannel, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

	// step: create a channel to receive events upon and add our resources for renewal
	updates := make(chan VaultEvent, 10)
	vault.AddListener(updates)

	// step: add each of the resources to the service processor
	for _, rn := range options.resources.items {
		if err := rn.IsValid(); err != nil {
			showUsage("%s", err)
		}
		vault.Watch(rn)
	}

	// step: we simply wait for events i.e. secrets from vault and write them to the output directory
	for {
		select {
		case evt := <-updates:
			go writeResource(evt.Resource, evt.Secret)

		case <-signalChannel:
			glog.Infof("recieved a termination signal, shutting down the service")
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package ciolite

// Imports
import (
	"fmt"
	"net/url"
	"reflect"
	"strings"
)

// CioParams struct with all possible query and post form values
type CioParams struct {
	BodyType             string `json:"body_type,omitempty"`
	CallbackURL          string `json:"callback_url,omitempty"`
	Delimiter            string `json:"delimiter,omitempty"`
	Email                string `json:"email,omitempty"`
	FailureNotifUrl      string `json:"failure_notif_url,omitempty"`
	FirstName            string `json:"first_name,omitempty"`
	FilterTo             string `json:"filter_to,omitempty"`
	FilterFrom           string `json:"filter_from,omitempty"`
	FilterCC             string `json:"filter_cc,omitempty"`
	FilterSubject        string `json:"filter_subject,omitempty"`
	FilterThread         string `json:"filter_thread,omitempty"`
	FilterNewImportant   string `json:"filter_new_important,omitempty"`
	FilterFileName       string `json:"filter_file_name,omitempty"`
	FilterFolderAdded    string `json:"filter_folder_added,omitempty"`
	FilterToDomain       string `json:"filter_to_domain,omitempty"`
	FilterFromDomain     string `json:"filter_from_domain,omitempty"`
	MigrateAccountID     string `json:"migrate_account_id,omitempty"`
	NewFolderID          string `json:"new_folder_id,omitempty"`
	LastName             string `json:"last_name,omitempty"`
	Password             string `json:"password,omitempty"`
	ProviderRefreshToken string `json:"provider_refresh_token,omitempty"`
	ProviderToken        string `json:"provider_token,omitempty"`
	ProviderTokenSecret  string `json:"provider_token_secret,omitempty"`
	ProviderConsumerKey  string `json:"provider_consumer_key,omitempty"`
	Server               string `json:"server,omitempty"`
	SourceType           string `json:"source_type,omitempty"`
	Status               string `json:"status,omitempty"`
	StatusCallbackURL    string `json:"status_callback_url,omitempty"`
	StatusOK             string `json:"status_ok,omitempty"`
	Type                 string `json:"type,omitempty"`
	Username             string `json:"username,omitempty"`

	Active            bool `json:"active,omitempty"`
	ForceStatusCheck  bool `json:"force_status_check,omitempty"`
	IncludeBody       bool `json:"include_body,omitempty"`
	IncludeHeaders    bool `json:"include_headers,omitempty"`
	IncludeFlags      bool `json:"include_flags,omitempty"`
	IncludeNamesOnly  bool `json:"include_names_only,omitempty"`
	Raw               bool `json:"raw,omitempty"`
	RawFileList       bool `json:"raw_file_list,omitempty"`
	SourceRawFileList bool `json:"source_raw_file_list,omitempty"`
	UseSSL            bool `json:"use_ssl,omitempty"`

	Limit  int `json:"limit,omitempty"`
	Offset int `json:"offset,omitempty"`
	Port   int `json:"port,omitempty"`
}

// FormValues returns valid FormValues for CIO Lite
func (cioParams CioParams) FormValues() url.Values {

	// Values
	values := url.Values{}

	// dynamically iterate through struct fields
	refVal := reflect.ValueOf(cioParams)
	refType := reflect.TypeOf(cioParams)
	for i, numFields := 0, refVal.NumField(); i < numFields; i++ {
		fieldValue := refVal.Field(i)
		fieldType := refType.Field(i)

		// dynamically choose how to fill the values based on field type
		// and set the key to the json tag name
		switch fieldValue.Kind() {

		case reflect.String:
			v := fieldValue.String()
			if len(v) > 0 {
				values.Set(jsonName(fieldType), v)
			}

		case reflect.Bool:
			v := fieldValue.Bool()
			if v {
				values.Set(jsonName(fieldType), "1")
			}

		case reflect.Int:
			v := fieldValue.Int()
			if v != 0 {
				values.Set(jsonName(fieldType), fmt.Sprintf("%d", v))
			}

		default:
			panic("Unexpected CioParams type: " + fieldValue.Kind().String())
		}
	}

	return values
}

// QueryString returns a query string
func (cioParams CioParams) QueryString() string {

	// Encode parameters
	encoded := cioParams.FormValues().Encode()
	if encoded == "" {
		return encoded
	}

	// Format
	return fmt.Sprintf("?%s", encoded)
}

// jsonName returns the json name based on the json tag of the struct field
func jsonName(sf reflect.StructField) string {
	jsonTag := sf.Tag.Get("json")
	return jsonTag[:strings.Index(jsonTag, ",")]
}
<commit_msg>protecting against missing or empty json name tag<commit_after>package ciolite

// Imports
import (
	"fmt"
	"net/url"
	"reflect"
	"strings"
)

// CioParams struct with all possible query and post form values
type CioParams struct {
	BodyType             string `json:"body_type,omitempty"`
	CallbackURL          string `json:"callback_url,omitempty"`
	Delimiter            string `json:"delimiter,omitempty"`
	Email                string `json:"email,omitempty"`
	FailureNotifUrl      string `json:"failure_notif_url,omitempty"`
	FirstName            string `json:"first_name,omitempty"`
	FilterTo             string `json:"filter_to,omitempty"`
	FilterFrom           string `json:"filter_from,omitempty"`
	FilterCC             string `json:"filter_cc,omitempty"`
	FilterSubject        string `json:"filter_subject,omitempty"`
	FilterThread         string `json:"filter_thread,omitempty"`
	FilterNewImportant   string `json:"filter_new_important,omitempty"`
	FilterFileName       string `json:"filter_file_name,omitempty"`
	FilterFolderAdded    string `json:"filter_folder_added,omitempty"`
	FilterToDomain       string `json:"filter_to_domain,omitempty"`
	FilterFromDomain     string `json:"filter_from_domain,omitempty"`
	MigrateAccountID     string `json:"migrate_account_id,omitempty"`
	NewFolderID          string `json:"new_folder_id,omitempty"`
	LastName             string `json:"last_name,omitempty"`
	Password             string `json:"password,omitempty"`
	ProviderRefreshToken string `json:"provider_refresh_token,omitempty"`
	ProviderToken        string `json:"provider_token,omitempty"`
	ProviderTokenSecret  string `json:"provider_token_secret,omitempty"`
	ProviderConsumerKey  string `json:"provider_consumer_key,omitempty"`
	Server               string `json:"server,omitempty"`
	SourceType           string `json:"source_type,omitempty"`
	Status               string `json:"status,omitempty"`
	StatusCallbackURL    string `json:"status_callback_url,omitempty"`
	StatusOK             string `json:"status_ok,omitempty"`
	Type                 string `json:"type,omitempty"`
	Username             string `json:"username,omitempty"`

	Active            bool `json:"active,omitempty"`
	ForceStatusCheck  bool `json:"force_status_check,omitempty"`
	IncludeBody       bool `json:"include_body,omitempty"`
	IncludeHeaders    bool `json:"include_headers,omitempty"`
	IncludeFlags      bool `json:"include_flags,omitempty"`
	IncludeNamesOnly  bool `json:"include_names_only,omitempty"`
	Raw               bool `json:"raw,omitempty"`
	RawFileList       bool `json:"raw_file_list,omitempty"`
	SourceRawFileList bool `json:"source_raw_file_list,omitempty"`
	UseSSL            bool `json:"use_ssl,omitempty"`

	Limit  int `json:"limit,omitempty"`
	Offset int `json:"offset,omitempty"`
	Port   int `json:"port,omitempty"`
}

// FormValues returns valid FormValues for CIO Lite
func (cioParams CioParams) FormValues() url.Values {

	// Values
	values := url.Values{}

	// dynamically iterate through struct fields
	refVal := reflect.ValueOf(cioParams)
	refType := reflect.TypeOf(cioParams)
	for i, numFields := 0, refVal.NumField(); i < numFields; i++ {
		fieldValue := refVal.Field(i)
		fieldType := refType.Field(i)

		// dynamically choose how to fill the values based on field type
		// and set the key to the json tag name
		switch fieldValue.Kind() {

		case reflect.String:
			v := fieldValue.String()
			if len(v) > 0 {
				values.Set(jsonName(fieldType), v)
			}

		case reflect.Bool:
			v := fieldValue.Bool()
			if v {
				values.Set(jsonName(fieldType), "1")
			}

		case reflect.Int:
			v := fieldValue.Int()
			if v != 0 {
				values.Set(jsonName(fieldType), fmt.Sprintf("%d", v))
			}

		default:
			panic("Unexpected CioParams type: " + fieldValue.Kind().String())
		}
	}

	return values
}

// QueryString returns a query string
func (cioParams CioParams) QueryString() string {

	// Encode parameters
	encoded := cioParams.FormValues().Encode()
	if encoded == "" {
		return encoded
	}

	// Format
	return fmt.Sprintf("?%s", encoded)
}

// jsonName returns the json name based on the json tag of the struct field
func jsonName(sf reflect.StructField) string {
	jsonTag := sf.Tag.Get("json")
	indexComma := strings.Index(jsonTag, ",")
	if len(jsonTag) == 0 || indexComma == 0 {
		panic(fmt.Sprintf("CioParam %s missing json name tag", sf.Name))
	}
	if indexComma >= 0 {
		return jsonTag[:indexComma]
	}
	return jsonTag
}
<|endoftext|>


<commit_before>package main

import (
	"gdcl/nsof"
	"gdcl/protocol"
	"io/ioutil"
	"os"
	"log"
	"encoding/hex"
)

func nsofTest() {
	bytes, _ := ioutil.ReadFile(os.Args[1])
	var in nsof.Data
	var out nsof.Data
	in = bytes[1:]
	objects := in.Factory()
	out = append(out, 2)
	objects[0].WriteNSOF(&out)
	log.Printf("\n%s\n", hex.Dump(out))
	ioutil.WriteFile("/tmp/g", out, 0644)
}

func dataHandler(receivedData <-chan protocol.DantePacket, sentData chan<- protocol.DantePacket, commands <-chan byte) {
	for {
		select {
		case packet := <-receivedData:
			log.Printf("%x\n", packet)
		case command := <-commands:
			log.Printf("Command: %d\n", command)
		}
	}
}

func commandReader() chan byte {
	out := make(chan byte)
	go func() {
		for {
			log.Println("Waiting for command")
			command := make([]byte, 1)
			for command[0] < 32 {
				os.Stdin.Read(command)
			}
			out <- command[0]
		}
	}()
	return out
}

func serialTest(session byte) {
	log.SetOutput(os.Stdout)
	commandChannel := commandReader()
	packetLayer := protocol.MNPPacketLayerNew(os.Args[1], 115200)
	connectionLayer := protocol.MNPConnectionLayerNew(packetLayer.ToConnection, packetLayer.FromConnection)
	dockLinkLayer := protocol.DockLinkLayerNew(connectionLayer.ToDockLink, connectionLayer.FromDockLink)
	connectModule := protocol.ConnectModuleNew(dockLinkLayer.FromApplication, session)
	dockLinkLayer.AddModule(connectModule)
	if session == protocol.SESSION_LOAD_PACKAGE {
		buf, _ := ioutil.ReadFile(os.Args[2])
		loadPackageModule := protocol.LoadPackageModuleNew(dockLinkLayer.FromApplication, buf)
		dockLinkLayer.AddModule(loadPackageModule)
	}
	dataHandler(dockLinkLayer.ToApplication, dockLinkLayer.FromApplication, commandChannel)
}

func main() {
	nsofTest()
	//serialTest(protocol.SESSION_LOAD_PACKAGE)
}
<commit_msg>Switch to connection test<commit_after>package main

import (
	"gdcl/nsof"
	"gdcl/protocol"
	"io/ioutil"
	"os"
	"log"
	"encoding/hex"
)

func nsofTest() {
	bytes, _ := ioutil.ReadFile(os.Args[1])
	var in nsof.Data
	var out nsof.Data
	in = bytes[1:]
	objects := in.Factory()
	out = append(out, 2)
	objects[0].WriteNSOF(&out)
	log.Printf("\n%s\n", hex.Dump(out))
	ioutil.WriteFile("/tmp/g", out, 0644)
}

func dataHandler(receivedData <-chan protocol.DantePacket, sentData chan<- protocol.DantePacket, commands <-chan byte) {
	for {
		select {
		case packet := <-receivedData:
			log.Printf("%x\n", packet)
		case command := <-commands:
			log.Printf("Command: %d\n", command)
		}
	}
}

func commandReader() chan byte {
	out := make(chan byte)
	go func() {
		for {
			log.Println("Waiting for command")
			command := make([]byte, 1)
			for command[0] < 32 {
				os.Stdin.Read(command)
			}
			out <- command[0]
		}
	}()
	return out
}

func serialTest(session byte) {
	log.SetOutput(os.Stdout)
	commandChannel := commandReader()
	packetLayer := protocol.MNPPacketLayerNew(os.Args[1], 115200)
	connectionLayer := protocol.MNPConnectionLayerNew(packetLayer.ToConnection, packetLayer.FromConnection)
	dockLinkLayer := protocol.DockLinkLayerNew(connectionLayer.ToDockLink, connectionLayer.FromDockLink)
	connectModule := protocol.ConnectModuleNew(dockLinkLayer.FromApplication, session)
	dockLinkLayer.AddModule(connectModule)
	if session == protocol.SESSION_LOAD_PACKAGE {
		buf, _ := ioutil.ReadFile(os.Args[2])
		loadPackageModule := protocol.LoadPackageModuleNew(dockLinkLayer.FromApplication, buf)
		dockLinkLayer.AddModule(loadPackageModule)
	}
	dataHandler(dockLinkLayer.ToApplication, dockLinkLayer.FromApplication, commandChannel)
}

func main() {
	//nsofTest()
	serialTest(protocol.SESSION_LOAD_PACKAGE)
}
<|endoftext|>


<commit_before>/*
Gist is a client for creating GitHub Gists.

	usage: gist [-v] [-p] [-a] [-d string] file ... | -f file

Gist uploads local file[s] to gist.github.com and prints information
about the created Gist. Default user is the authenticated user.

Authentication

Gist expects to find a GitHub "personal access token" in
$HOME/.github-gist-token and will that token to authenticate
to Github when writing Gist data.
A token can be created by visiting https://github.com/settings/tokens/new.
The token only needs the 'gist' scope checkbox.
It does not need any other permissions.
The -token flag specifies an alternate file from which to read the token.

*/
package main // import "kkn.fi/cmd/gist"

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"golang.org/x/oauth2"

	"github.com/google/go-github/github"
)

var (
	version    string
	date       string
	v          = flag.Bool("v", false, "print version and exit")
	descFlag   = flag.String("d", "", "description for Gist")
	publicFlag = flag.Bool("p", false, "create a public Gist")
	anonFlag   = flag.Bool("a", false, "create anonymous Gist")
	fileFlag   = flag.String("f", "", "file name of the Gist. Reads file contents from stdin")
	tokenFile  = flag.String("token", "", "read GitHub personal access token from `file` (default $HOME/.github-gist-token)")
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: gist [-v] [-d string] [-p] [-a] file ... | -f file\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = usage
	flag.Parse()
	log.SetFlags(0)
	log.SetPrefix("gist: ")

	if *v {
		fmt.Printf("%v: %v %v %v\n", path.Base(os.Args[0]), version, date, runtime.Version())
		os.Exit(0)
	}
	if *fileFlag == "" && len(flag.Args()) == 0 {
		usage()
	}
	filenames := flag.Args()
	files := make(map[github.GistFilename]github.GistFile)
	for _, f := range filenames {
		file := string(f)
		buf, err := ioutil.ReadFile(file)
		if err != nil {
			log.Fatal(err)
		}
		content := string(buf)
		gistFile := github.GistFile{
			Filename: &file,
			Content:  &content,
		}
		files[github.GistFilename(file)] = gistFile
	}
	if *fileFlag != "" {
		buf, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			log.Fatal(err)
		}
		content := string(buf)
		gistFile := github.GistFile{
			Filename: fileFlag,
			Content:  &content,
		}
		files[github.GistFilename(*fileFlag)] = gistFile
	}

	if !*anonFlag {
		loadAuth()
	} else {
		client = github.NewClient(nil)
	}

	gist := &github.Gist{
		Description: descFlag,
		Public:      publicFlag,
		Files:       files,
	}
	timeout := time.Second * time.Duration(5)
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	g, _, err := client.Gists.Create(ctx, gist)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%v\n", *g.HTMLURL)
}

var client *github.Client

// GitHub personal access token, from https://github.com/settings/applications.
var authToken string

func loadAuth() {
	const short = ".github-gist-token"
	filename := filepath.Clean(os.Getenv("HOME") + "/" + short)
	shortFilename := filepath.Clean("$HOME/" + short)
	if *tokenFile != "" {
		filename = *tokenFile
		shortFilename = *tokenFile
	}
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatal("reading token: ", err, "\n\n"+
			"Please create a personal access token at https://github.com/settings/tokens/new\n"+
			"and write it to ", shortFilename, " to use this program.\n"+
			"The token only needs the repo scope, or private_repo if you want to\n"+
			"view or edit issues for private repositories.\n"+
			"The benefit of using a personal access token over using your GitHub\n"+
			"password directly is that you can limit its use and revoke it at any time.\n\n")
	}
	fi, err := os.Stat(filename)
	if fi.Mode()&0077 != 0 {
		log.Fatalf("reading token: %s mode is %#o, want %#o", shortFilename, fi.Mode()&0777, fi.Mode()&0700)
	}
	authToken = strings.TrimSpace(string(data))
	t := &oauth2.Transport{
		Source: &tokenSource{AccessToken: authToken},
	}
	client = github.NewClient(&http.Client{Transport: t})
}

type tokenSource oauth2.Token

func (t *tokenSource) Token() (*oauth2.Token, error) {
	return (*oauth2.Token)(t), nil
}
<commit_msg>Add error handling to os.Stat() call<commit_after>/*
Gist is a client for creating GitHub Gists.

	usage: gist [-v] [-p] [-a] [-d string] file ... | -f file

Gist uploads local file[s] to gist.github.com and prints information
about the created Gist. Default user is the authenticated user.

Authentication

Gist expects to find a GitHub "personal access token" in
$HOME/.github-gist-token and will that token to authenticate
to Github when writing Gist data.
A token can be created by visiting https://github.com/settings/tokens/new.
The token only needs the 'gist' scope checkbox.
It does not need any other permissions.
The -token flag specifies an alternate file from which to read the token.

*/
package main // import "kkn.fi/cmd/gist"

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"golang.org/x/oauth2"

	"github.com/google/go-github/github"
)

var (
	version    string
	date       string
	v          = flag.Bool("v", false, "print version and exit")
	descFlag   = flag.String("d", "", "description for Gist")
	publicFlag = flag.Bool("p", false, "create a public Gist")
	anonFlag   = flag.Bool("a", false, "create anonymous Gist")
	fileFlag   = flag.String("f", "", "file name of the Gist. Reads file contents from stdin")
	tokenFile  = flag.String("token", "", "read GitHub personal access token from `file` (default $HOME/.github-gist-token)")
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: gist [-v] [-d string] [-p] [-a] file ... | -f file\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = usage
	flag.Parse()
	log.SetFlags(0)
	log.SetPrefix("gist: ")

	if *v {
		fmt.Printf("%v: %v %v %v\n", path.Base(os.Args[0]), version, date, runtime.Version())
		os.Exit(0)
	}
	if *fileFlag == "" && len(flag.Args()) == 0 {
		usage()
	}
	filenames := flag.Args()
	files := make(map[github.GistFilename]github.GistFile)
	for _, f := range filenames {
		file := string(f)
		buf, err := ioutil.ReadFile(file)
		if err != nil {
			log.Fatal(err)
		}
		content := string(buf)
		gistFile := github.GistFile{
			Filename: &file,
			Content:  &content,
		}
		files[github.GistFilename(file)] = gistFile
	}
	if *fileFlag != "" {
		buf, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			log.Fatal(err)
		}
		content := string(buf)
		gistFile := github.GistFile{
			Filename: fileFlag,
			Content:  &content,
		}
		files[github.GistFilename(*fileFlag)] = gistFile
	}

	if !*anonFlag {
		loadAuth()
	} else {
		client = github.NewClient(nil)
	}

	gist := &github.Gist{
		Description: descFlag,
		Public:      publicFlag,
		Files:       files,
	}
	timeout := time.Second * time.Duration(5)
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	g, _, err := client.Gists.Create(ctx, gist)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%v\n", *g.HTMLURL)
}

var client *github.Client

// GitHub personal access token, from https://github.com/settings/applications.
var authToken string

func loadAuth() {
	const short = ".github-gist-token"
	filename := filepath.Clean(os.Getenv("HOME") + "/" + short)
	shortFilename := filepath.Clean("$HOME/" + short)
	if *tokenFile != "" {
		filename = *tokenFile
		shortFilename = *tokenFile
	}
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Fatal("reading token: ", err, "\n\n"+
			"Please create a personal access token at https://github.com/settings/tokens/new\n"+
			"and write it to ", shortFilename, " to use this program.\n"+
			"The token only needs the repo scope, or private_repo if you want to\n"+
			"view or edit issues for private repositories.\n"+
			"The benefit of using a personal access token over using your GitHub\n"+
			"password directly is that you can limit its use and revoke it at any time.\n\n")
	}
	fi, err := os.Stat(filename)
	if err != nil {
		log.Fatal(err)
	}
	if fi.Mode()&0077 != 0 {
		log.Fatalf("reading token: %s mode is %#o, want %#o", shortFilename, fi.Mode()&0777, fi.Mode()&0700)
	}
	authToken = strings.TrimSpace(string(data))
	t := &oauth2.Transport{
		Source: &tokenSource{AccessToken: authToken},
	}
	client = github.NewClient(&http.Client{Transport: t})
}

type tokenSource oauth2.Token

func (t *tokenSource) Token() (*oauth2.Token, error) {
	return (*oauth2.Token)(t), nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
)

type Model struct {
	Name   string
	Fields map[string]string
}

func parseFile(path string) error {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, 0)

	if err != nil {
		return err
	}

	models := []*Model{}

	ast.Inspect(f, func(node ast.Node) bool {
		switch x := node.(type) {
		case *ast.GenDecl:
			if x.Tok != token.TYPE {
				break
			}

			for _, spec := range x.Specs {
				fieldNames := []string{}
				fields := make(map[string]string)

				var modelName string

				switch x2 := spec.(type) {
				case *ast.TypeSpec:
					modelName = x2.Name.Name

					switch x3 := x2.Type.(type) {
					case *ast.StructType:
						for _, field := range x3.Fields.List {
							for _, name := range field.Names {
								fieldNames = append(fieldNames, name.Name)
							}

							var fieldType string

							switch x4 := field.Type.(type) {
							case *ast.Ident: // e.g. string
								fieldType = x4.Name
							case *ast.StarExpr: // e.g. *time.Time
								switch x5 := x4.X.(type) {
								case *ast.SelectorExpr:
									switch x6 := x5.X.(type) {
									case *ast.Ident:
										fieldType = x6.Name + "." + x5.Sel.Name
									}
								}
							}

							for _, name := range fieldNames {
								fields[name] = fieldType
							}
						}
					}

					models = append(models, &Model{
						Name:   modelName,
						Fields: fields,
					})
				}
			}
		}

		return true
	})

	for _, model := range models {
		fmt.Println("Model: " + model.Name)
		fmt.Println("Fields: ")

		for name, t := range model.Fields {
			fmt.Println("  - " + name + " => " + t)
		}
	}

	return nil
}

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, "usage: api-server-generator <model directory>")
		os.Exit(1)
	}

	dir := os.Args[1]

	files, err := ioutil.ReadDir(dir)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	for _, file := range files {
		if file.IsDir() {
			continue
		}

		path := filepath.Join(dir, file.Name())
		fmt.Println("===== " + path)

		if err := parseFile(path); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}
}
<commit_msg>Generate controller code from AST<commit_after>package main

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/gedex/inflector"
)

type Model struct {
	Name   string
	Fields map[string]string
}

var controllerTmpl = `
func Get{{ pluralize .Name }}(c *gin.Context) {
	db := db.DBInstance(c)
	fields := c.DefaultQuery("fields", "*")
	var {{ pluralize (tolower .Name) }} []models.{{ .Name }}
	db.Select(fields).Find(&{{ pluralize (tolower .Name) }})
	c.JSON(200, {{ pluralize (tolower .Name) }})
}

func Get{{ .Name }}(c. *gin.Context) {
	db := db.DBInstance(c)
	id := c.Params.ByName("id")
	fields := c.DefaultQuery("fields", "*")
	var {{ tolower .Name }} models.{{ .Name }}
	err := db.Select(fields).First(&{{ tolower .Name }}, id).Error

	if err != nil {
		content := gin.H{"error": "{{ tolower .Name }} with id#" + id + " not found"}
		c.JSON(404, content)
		return
	}

	c.JSON(200, {{ tolower .Name }})
}

func Create{{ .Name }}(c *gin.Context) {
	db := db.DBInstance(c)
	var {{ tolower .Name }} models.{{ .Name }}
	c.Bind(&{{ tolower .Name }})
	if db.Create(&{{ tolower .Name }}).Error != nil {
		content := gin.H{"error": "error occured"}
		c.JSON(500, content)
		return
	}
	c.JSON(201, {{ tolower .Name }})
}

func Update{{ .Name }}(c *gin.Context) {
	db := db.DBInstance(c)
	id := c.Params.ByName("id")
	var {{ tolower .Name }} models.{{ .Name }}
	if db.First(&{{ tolower .Name }}, id).Error != nil {
		content := gin.H{"error": "{{ tolower .Name }} with id#" + id + " not found"}
		c.JSON(404, content)
		return
	}
	c.Bind(&{{ tolower .Name }})
	db.Save(&{{ tolower .Name }})
	c.JSON(200, {{ tolower .Name }})
}

func Delete{{ .Name }}(c *gin.Context) {
	db := db.DBInstance(c)
	id := c.Params.ByName("id")
	var {{ tolower .Name }} models.{{ .Name }}
	if db.First(&{{ tolower .Name }}, id).Error != nil {
		content := gin.H{"error": "{{ tolower .Name }} with id#" + id + " not found"}
		c.JSON(404, content)
		return
	}
	db.Delete(&{{ tolower .Name }})
	c.Writer.WriteHeader(http.StatusNoContent)
}
`

var funcMap = template.FuncMap{
	"pluralize": inflector.Pluralize,
	"tolower":   strings.ToLower,
}

func generateController(model *Model) (string, error) {
	tmpl, err := template.New("controller").Funcs(funcMap).Parse(controllerTmpl)

	if err != nil {
		return "", nil
	}

	var buf bytes.Buffer

	if err := tmpl.Execute(&buf, model); err != nil {
		return "", nil
	}

	return strings.TrimSpace(buf.String()), nil
}

func parseFile(path string) ([]*Model, error) {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, 0)

	if err != nil {
		return nil, err
	}

	models := []*Model{}

	ast.Inspect(f, func(node ast.Node) bool {
		switch x := node.(type) {
		case *ast.GenDecl:
			if x.Tok != token.TYPE {
				break
			}

			for _, spec := range x.Specs {
				fieldNames := []string{}
				fields := make(map[string]string)

				var modelName string

				switch x2 := spec.(type) {
				case *ast.TypeSpec:
					modelName = x2.Name.Name

					switch x3 := x2.Type.(type) {
					case *ast.StructType:
						for _, field := range x3.Fields.List {
							for _, name := range field.Names {
								fieldNames = append(fieldNames, name.Name)
							}

							var fieldType string

							switch x4 := field.Type.(type) {
							case *ast.Ident: // e.g. string
								fieldType = x4.Name
							case *ast.StarExpr: // e.g. *time.Time
								switch x5 := x4.X.(type) {
								case *ast.SelectorExpr:
									switch x6 := x5.X.(type) {
									case *ast.Ident:
										fieldType = x6.Name + "." + x5.Sel.Name
									}
								}
							}

							for _, name := range fieldNames {
								fields[name] = fieldType
							}
						}
					}

					models = append(models, &Model{
						Name:   modelName,
						Fields: fields,
					})
				}
			}
		}

		return true
	})

	return models, nil
}

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, "usage: api-server-generator <model directory>")
		os.Exit(1)
	}

	dir := os.Args[1]

	files, err := ioutil.ReadDir(dir)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	for _, file := range files {
		if file.IsDir() {
			continue
		}

		path := filepath.Join(dir, file.Name())
		fmt.Println("===== " + path)

		models, err := parseFile(path)

		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}

		for _, model := range models {
			fmt.Println("// Model: " + model.Name)
			fmt.Println("// Fields: ")

			for name, t := range model.Fields {
				fmt.Println("//  - " + name + " => " + t)
			}

			fmt.Println("")

			controller, err := generateController(model)

			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1)
			}

			fmt.Println(controller)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"

	"github.com/ogier/pflag"
)

var (
	name    = "csvp"
	version = "0.10.0"

	flagset         = pflag.NewFlagSet(name, pflag.ContinueOnError)
	indexesList     = flagset.StringP("indexes", "i", "", "")
	headersList     = flagset.StringP("headers", "h", "", "")
	isTSV           = flagset.BoolP("tsv", "t", false, "")
	delimiter       = flagset.StringP("delimiter", "d", ",", "")
	outputDelimiter = flagset.StringP("output-delimiter", "D", "\t", "")
	isHelp          = flagset.BoolP("help", "", false, "")
	isVersion       = flagset.BoolP("version", "", false, "")
)

func printUsage() {
	fmt.Fprintf(os.Stderr, `
Usage: %s [OPTION]... [FILE]...
Print selected parts of CSV from each FILE to standard output.

Options:
  -i, --indexes=LIST
                 select only these indexes
  -h, --headers=LIST
                 select only these headers
  -t, --tsv
                 equivalent to -d'\t'
  -d, --delimiter=DELIM
                 use DELIM instead of comma for field delimiter
  -D, --output-delimiter=STRING
                 use STRING as the output delimiter (default: \t)
  --help
                 display this help text and exit
  --version
                 output version information and exit
`[1:], name)
}

func printVersion() {
	fmt.Fprintln(os.Stderr, version)
}

func printErr(err interface{}) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", name, err)
}

func guideToHelp() {
	fmt.Fprintf(os.Stderr, "Try '%s --help' for more information.\n", name)
}

func toDelimiter(s string) (ch rune, err error) {
	s, err = strconv.Unquote(`"` + s + `"`)
	if err != nil {
		return 0, err
	}

	a := []rune(s)
	if len(a) != 1 {
		return 0, fmt.Errorf("the delimiter must be a single character")
	}
	return a[0], nil
}

func do(c *CSVScanner) error {
	for c.Scan() {
		fmt.Println(c.Text())
	}
	return c.Err()
}

func _main() int {
	flagset.SetOutput(ioutil.Discard)
	if err := flagset.Parse(os.Args[1:]); err != nil {
		printErr(err)
		guideToHelp()
		return 2
	}
	if *isHelp {
		printUsage()
		return 0
	}
	if *isVersion {
		printVersion()
		return 0
	}

	var selector Selector
	switch {
	case *indexesList != "" && *headersList != "":
		printErr("only one type of list may be specified")
		guideToHelp()
		return 2
	case *indexesList != "":
		selector = NewIndexes(*indexesList)
	case *headersList != "":
		selector = NewHeaders(*headersList)
	default:
		selector = NewAll()
	}

	c := NewCSVScanner(selector, nil)
	c.SetOutputDelimiter(*outputDelimiter)
	switch {
	case *isTSV:
		c.SetDelimiter('\t')
	default:
		ch, err := toDelimiter(*delimiter)
		if err != nil {
			printErr(err)
			guideToHelp()
			return 2
		}
		c.SetDelimiter(ch)
	}

	var rs []io.Reader
	if flagset.NArg() == 0 {
		rs = append(rs, os.Stdin)
	} else {
		for _, path := range flagset.Args() {
			f, err := os.Open(path)
			if err != nil {
				printErr(err)
				guideToHelp()
				return 2
			}
			defer f.Close()

			rs = append(rs, f)
		}
	}

	for _, r := range rs {
		c.InitializeReader(r)
		if err := do(c); err != nil {
			printErr(err)
			return 1
		}
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<commit_msg>Upgrade to fix a bug. stdin wasn't read<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"

	"github.com/ogier/pflag"
)

var (
	name    = "csvp"
	version = "0.10.1"

	flagset         = pflag.NewFlagSet(name, pflag.ContinueOnError)
	indexesList     = flagset.StringP("indexes", "i", "", "")
	headersList     = flagset.StringP("headers", "h", "", "")
	isTSV           = flagset.BoolP("tsv", "t", false, "")
	delimiter       = flagset.StringP("delimiter", "d", ",", "")
	outputDelimiter = flagset.StringP("output-delimiter", "D", "\t", "")
	isHelp          = flagset.BoolP("help", "", false, "")
	isVersion       = flagset.BoolP("version", "", false, "")
)

func printUsage() {
	fmt.Fprintf(os.Stderr, `
Usage: %s [OPTION]... [FILE]...
Print selected parts of CSV from each FILE to standard output.

Options:
  -i, --indexes=LIST
                 select only these indexes
  -h, --headers=LIST
                 select only these headers
  -t, --tsv
                 equivalent to -d'\t'
  -d, --delimiter=DELIM
                 use DELIM instead of comma for field delimiter
  -D, --output-delimiter=STRING
                 use STRING as the output delimiter (default: \t)
  --help
                 display this help text and exit
  --version
                 output version information and exit
`[1:], name)
}

func printVersion() {
	fmt.Fprintln(os.Stderr, version)
}

func printErr(err interface{}) {
	fmt.Fprintf(os.Stderr, "%s: %s\n", name, err)
}

func guideToHelp() {
	fmt.Fprintf(os.Stderr, "Try '%s --help' for more information.\n", name)
}

func toDelimiter(s string) (ch rune, err error) {
	s, err = strconv.Unquote(`"` + s + `"`)
	if err != nil {
		return 0, err
	}

	a := []rune(s)
	if len(a) != 1 {
		return 0, fmt.Errorf("the delimiter must be a single character")
	}
	return a[0], nil
}

func do(c *CSVScanner) error {
	for c.Scan() {
		fmt.Println(c.Text())
	}
	return c.Err()
}

func _main() int {
	flagset.SetOutput(ioutil.Discard)
	if err := flagset.Parse(os.Args[1:]); err != nil {
		printErr(err)
		guideToHelp()
		return 2
	}
	if *isHelp {
		printUsage()
		return 0
	}
	if *isVersion {
		printVersion()
		return 0
	}

	var selector Selector
	switch {
	case *indexesList != "" && *headersList != "":
		printErr("only one type of list may be specified")
		guideToHelp()
		return 2
	case *indexesList != "":
		selector = NewIndexes(*indexesList)
	case *headersList != "":
		selector = NewHeaders(*headersList)
	default:
		selector = NewAll()
	}

	c := NewCSVScanner(selector, nil)
	c.SetOutputDelimiter(*outputDelimiter)
	switch {
	case *isTSV:
		c.SetDelimiter('\t')
	default:
		ch, err := toDelimiter(*delimiter)
		if err != nil {
			printErr(err)
			guideToHelp()
			return 2
		}
		c.SetDelimiter(ch)
	}

	var rs []io.Reader
	if flagset.NArg() == 0 {
		rs = append(rs, os.Stdin)
	} else {
		for _, path := range flagset.Args() {
			f, err := os.Open(path)
			if err != nil {
				printErr(err)
				guideToHelp()
				return 2
			}
			defer f.Close()

			rs = append(rs, f)
		}
	}

	for _, r := range rs {
		c.InitializeReader(r)
		if err := do(c); err != nil {
			printErr(err)
			return 1
		}
	}
	return 0
}

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


<commit_before>package mandira

import (
	"fmt"
	"strconv"
)

/* Parser for the extended features in Mandira.

word = ([a-zA-Z1-9]+)
dot = .
binop = <|<=|>|>=|!=|==
comb = or|and
unary = not
filter = |
variable = word
string = " .* "
int = [0-9]+
float = int dot [int]
bool = true | false
atom = variable | string | int | float | bool
funcexpr = word [( atom[, atom...] )]
varexpr = variable [|funcexpr...]

The following grammar describes a simplified, easy to implement boolean algebra.

Conditions can be a varexpr (var|filter...) or a negated var expr.
Binary Conditions must be two of these joined by a numeric binop
ConditionalExpressions are either one Condition (either type), or two joined by
a boolean combinator (and/or).

Multiple and/or is prohibited.  Grouping is unnecessary.  To achieve more complex
logic, use multiple conditional blocks. Numeric operators take precedence over and/or.
Binary logic is evaluated from left to right, and & ors are short circuited by
false & true values in the lhs, respectively.

cond = varexpr | not varexpr
bincond = cond binop cond
boolexpr = cond | bincond
condexpr = boolexpr [comb boolexpr]

*/

// -- Literals

type lookupExpr struct {
	name string
}

type funcExpr struct {
	name string
	// these are either literal values or lookup expressions
	arguments []interface{}
}

type cond struct {
	not  bool
	expr interface{}
}

type bincond struct {
	oper string
	lhs  cond
	rhs  cond
}

type condExpr struct {
	combinator string
	exprs      []interface{}
}

type varExpr struct {
	exprs []interface{}
}

type tokenList struct {
	tokens []string
	p      int
	run    int
}

// Return the number of remaining tokens
func (t *tokenList) Remaining() int {
	return len(t.tokens) - t.p
}

// Return the next token.  Returns "" if there are none left.
func (t *tokenList) Next() string {
	if t.p == len(t.tokens) {
		return ""
	}
	t.p++
	return t.tokens[t.p-1]
}

// Peek at the current token. Returns "" if there are none left.
func (t *tokenList) Peek() string {
	if t.p == len(t.tokens) {
		return ""
	}
	return t.tokens[t.p]
}

type parserError struct {
	tokens  *tokenList
	message string
}

func (p *parserError) Error() string {
	return fmt.Sprintf(`%s: "%s" in %v`, p.message, p.tokens.Peek(), p.tokens)
}

// Parse an atom;  an atom is a literal or a lookup expression.
// lookup expressions can have any text but whitespace in them
func parseAtom(token string) interface{} {
	if token[0] == '"' {
		return token[1 : len(token)-1]
	}
	i, err := strconv.ParseInt(token, 10, 64)
	if err == nil {
		return i
	}
	f, err := strconv.ParseFloat(token, 64)
	if err == nil {
		return f
	}
	return &lookupExpr{token}
}

// parse a single unary condition (or naked varexpr)
func parseCond(tokens []string) (*cond, error) {
	return &cond{}, nil
}

// Parse a condition, which can be:
//   variable
//   not condition
//   "(" condition ")"
//   condition binary condition
func parseCondExpression(tokens []string) (interface{}, error) {
	return nil, nil
}

func parseFuncExpression(tokens *tokenList) (*funcExpr, error) {
	fe := &funcExpr{}
	fe.name = tokens.Next()
	if len(fe.name) == 0 {
		return fe, &parserError{tokens, "Expected filter name, got nil"}
	}
	tok := tokens.Peek()
	if tok == "(" {
		tokens.Next()
		for tok = tokens.Next(); len(tok) > 0; tok = tokens.Next() {
			fe.arguments = append(fe.arguments, parseAtom(tok))
			tok = tokens.Next()
			if tok == ")" {
				break
			}
			if tok != "," {
				return fe, &parserError{tokens, "Expected comma (,)"}
			}
		}
	}

	return fe, nil
}

func parseVarExpression(tokens *tokenList) (*varExpr, error) {

	expr := &varExpr{}
	tok := tokens.Next()
	if len(tok) == 0 {
		return expr, &parserError{tokens, "Empty expression"}
	}
	// the first token is definitely a variable
	expr.exprs = append(expr.exprs, &lookupExpr{tok})

	tok = tokens.Next()
	if tok != "|" && tok != "" {
		return expr, nil
	}

	for len(tok) > 0 {
		if tok == "|" {
			e, err := parseFuncExpression(tokens)
			if err != nil {
				return expr, err
			}
			expr.exprs = append(expr.exprs, e)
			tok = tokens.Next()
		} else {
			return expr, nil
		}
	}

	return expr, nil
}

// tokenize a conditional, return a list of strings
func tokenize(c string) ([]string, error) {
	b := []byte(c)
	tn := tokenList{[]string{}, 0, 0}

	for ; tn.p < len(b); tn.p++ {
		switch b[tn.p] {
		case ' ', '\t':
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			tn.run = tn.p + 1
		/* tokens which can be singular or double */
		case '<', '>':
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			if tn.p+1 < len(b) && b[tn.p+1] == '=' {
				tn.tokens = append(tn.tokens, string(b[tn.p:tn.p+2]))
				tn.p++
			} else {
				tn.tokens = append(tn.tokens, string(b[tn.p]))
			}
			tn.run = tn.p + 1
		/* tokens which must be double */
		case '!', '=':
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			if tn.p+1 < len(b) && b[tn.p+1] == '=' {
				tn.tokens = append(tn.tokens, string(b[tn.p:tn.p+2]))
				tn.p++
			} else {
				return tn.tokens, parseError{tn.p, "invalid token: " + string(b[tn.p])}
			}
			tn.run = tn.p + 1
		case '"':
			start := tn.p
			tn.p++
			for ; tn.p < len(b); tn.p++ {
				if b[tn.p] == '"' && b[tn.p-1] != '\\' {
					tn.tokens = append(tn.tokens, string(b[start:tn.p+1]))
					break
				}
			}
			tn.run = tn.p + 1
		/* tokens which are only ever single */
		case '|', '(', ')', ',':
			if tn.p > 0 && b[tn.p] == '\\' && b[tn.p] == '"' {
				tn.run = tn.p + 1
				continue
			}
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			tn.tokens = append(tn.tokens, string(b[tn.p]))
			tn.run = tn.p + 1
		default:

		}
	}

	if tn.run < len(b) {
		tn.tokens = append(tn.tokens, string(b[tn.run:]))
	}
	return tn.tokens, nil
}
<commit_msg>rewrite parser functions to take a token list which has a pointer to the current token and next/peek/remaining methods, simplifying them a lot<commit_after>package mandira

import (
	"fmt"
	"strconv"
)

/* Parser for the extended features in Mandira.

word = ([a-zA-Z1-9]+)
dot = .
binop = <|<=|>|>=|!=|==
comb = or|and
unary = not
filter = |
variable = word
string = " .* "
int = [0-9]+
float = int dot [int]
bool = true | false
atom = variable | string | int | float | bool
funcexpr = word [( atom[, atom...] )]
varexpr = variable [|funcexpr...]

The following grammar describes a simplified, easy to implement boolean algebra.

Conditions can be a varexpr (var|filter...) or a negated var expr.
Binary Conditions must be two of these joined by a numeric binop
ConditionalExpressions are either one Condition (either type), or two joined by
a boolean combinator (and/or).

Multiple and/or is prohibited.  Grouping is unnecessary.  To achieve more complex
logic, use multiple conditional blocks. Numeric operators take precedence over and/or.
Binary logic is evaluated from left to right, and & ors are short circuited by
false & true values in the lhs, respectively.

cond = varexpr | not varexpr
bincond = cond binop cond
boolexpr = cond | bincond
condexpr = boolexpr [comb boolexpr]

*/

// -- Literals

type lookupExpr struct {
	name string
}

type funcExpr struct {
	name string
	// these are either literal values or lookup expressions
	arguments []interface{}
}

type cond struct {
	not  bool
	expr interface{}
}

type bincond struct {
	oper string
	lhs  cond
	rhs  cond
}

type condExpr struct {
	oper string
	lhs  interface{}
	rhs  interface{}
}

type varExpr struct {
	exprs []interface{}
}

type tokenList struct {
	tokens []string
	p      int
	run    int
}

// Return the number of remaining tokens
func (t *tokenList) Remaining() int {
	return len(t.tokens) - t.p
}

// Return the next token.  Returns "" if there are none left.
func (t *tokenList) Next() string {
	if t.p == len(t.tokens) {
		return ""
	}
	t.p++
	return t.tokens[t.p-1]
}

// Peek at the current token. Returns "" if there are none left.
func (t *tokenList) Peek() string {
	if t.p == len(t.tokens) {
		return ""
	}
	return t.tokens[t.p]
}

type parserError struct {
	tokens  *tokenList
	message string
}

func (p *parserError) Error() string {
	return fmt.Sprintf(`%s: "%s" in %v`, p.message, p.tokens.Peek(), p.tokens)
}

// Parse an atom;  an atom is a literal or a lookup expression.
// lookup expressions can have any text but whitespace in them
func parseAtom(token string) interface{} {
	if token[0] == '"' {
		return token[1 : len(token)-1]
	}
	i, err := strconv.ParseInt(token, 10, 64)
	if err == nil {
		return i
	}
	f, err := strconv.ParseFloat(token, 64)
	if err == nil {
		return f
	}
	return &lookupExpr{token}
}

// parse a single unary condition (or naked varexpr)
func parseCond(tokens *tokenList) (*cond, error) {
	var err error
	c := &cond{}
	tok := tokens.Peek()
	if tok == "not" {
		c.not = true
		tokens.Next()
	}
	c.expr, err = parseVarExpression(tokens)
	return c, err
}

// parse a unary or binary boolean expression and return it.
// Valid return values are of type cond or bincond
func parseBoolExpression(tokens *tokenList) (interface{}, error) {
	c, err := parseCond(tokens)
	if err != nil {
		return c, err
	}
	tok := tokens.Peek()
	switch tok {
	case "<", "<=", ">", ">=", "==", "!=":
		tokens.Next()
		c2, err := parseCond(tokens)
		if err != nil {
			return c2, err
		}
		return &bincond{tok, c, c2}, nil
	}
	return c, nil
}

// Parse a condition, which can be:
//   variable
//   not condition
//   "(" condition ")"
//   condition binary condition
func parseCondExpression(tokens []string) (*condExpr, error) {
	var err error
	c := &condExpr{}
	c.lhs, err = parseBoolExpression(tokens)

	if err != nil {
		return &condExpr{}, err
	}

	tok := tokens.Peek()
	switch tok {
	case "and", "or":
		c.oper = tok
		tokens.Next()
		c.rhs, err = parseBoolExpression(tokens)
		if err != nil {
			return c, err
		}
		return c
	}
	return c
}

func parseFuncExpression(tokens *tokenList) (*funcExpr, error) {
	fe := &funcExpr{}
	fe.name = tokens.Next()
	if len(fe.name) == 0 {
		return fe, &parserError{tokens, "Expected filter name, got nil"}
	}
	tok := tokens.Peek()
	if tok == "(" {
		tokens.Next()
		for tok = tokens.Next(); len(tok) > 0; tok = tokens.Next() {
			fe.arguments = append(fe.arguments, parseAtom(tok))
			tok = tokens.Next()
			if tok == ")" {
				break
			}
			if tok != "," {
				return fe, &parserError{tokens, "Expected comma (,)"}
			}
		}
	}

	return fe, nil
}

func parseVarExpression(tokens *tokenList) (*varExpr, error) {

	expr := &varExpr{}
	tok := tokens.Next()
	if len(tok) == 0 {
		return expr, &parserError{tokens, "Empty expression"}
	}
	// the first token is definitely a variable
	expr.exprs = append(expr.exprs, &lookupExpr{tok})

	tok = tokens.Next()
	if tok != "|" && tok != "" {
		return expr, nil
	}

	for len(tok) > 0 {
		if tok == "|" {
			e, err := parseFuncExpression(tokens)
			if err != nil {
				return expr, err
			}
			expr.exprs = append(expr.exprs, e)
			tok = tokens.Next()
		} else {
			return expr, nil
		}
	}

	return expr, nil
}

// tokenize a conditional, return a list of strings
func tokenize(c string) ([]string, error) {
	b := []byte(c)
	tn := tokenList{[]string{}, 0, 0}

	for ; tn.p < len(b); tn.p++ {
		switch b[tn.p] {
		case ' ', '\t':
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			tn.run = tn.p + 1
		/* tokens which can be singular or double */
		case '<', '>':
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			if tn.p+1 < len(b) && b[tn.p+1] == '=' {
				tn.tokens = append(tn.tokens, string(b[tn.p:tn.p+2]))
				tn.p++
			} else {
				tn.tokens = append(tn.tokens, string(b[tn.p]))
			}
			tn.run = tn.p + 1
		/* tokens which must be double */
		case '!', '=':
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			if tn.p+1 < len(b) && b[tn.p+1] == '=' {
				tn.tokens = append(tn.tokens, string(b[tn.p:tn.p+2]))
				tn.p++
			} else {
				return tn.tokens, parseError{tn.p, "invalid token: " + string(b[tn.p])}
			}
			tn.run = tn.p + 1
		case '"':
			start := tn.p
			tn.p++
			for ; tn.p < len(b); tn.p++ {
				if b[tn.p] == '"' && b[tn.p-1] != '\\' {
					tn.tokens = append(tn.tokens, string(b[start:tn.p+1]))
					break
				}
			}
			tn.run = tn.p + 1
		/* tokens which are only ever single */
		case '|', '(', ')', ',':
			if tn.p > 0 && b[tn.p] == '\\' && b[tn.p] == '"' {
				tn.run = tn.p + 1
				continue
			}
			if tn.run < tn.p {
				tn.tokens = append(tn.tokens, string(b[tn.run:tn.p]))
			}
			tn.tokens = append(tn.tokens, string(b[tn.p]))
			tn.run = tn.p + 1
		default:

		}
	}

	if tn.run < len(b) {
		tn.tokens = append(tn.tokens, string(b[tn.run:]))
	}
	return tn.tokens, nil
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/synful/rate"
)

var (
	unit     = flag.String("unit", "KB", "Unit for displaying rate. Options are B, KB, KiB, MB, MiB, GB, GiB.")
	progress = flag.Bool("progress", false, "Display the total amount of data copied so far.")
)

const (
	EXIT_USAGE = 2 + iota
	EXIT_IO
)

var units = map[string]int{
	"B":   1,
	"KB":  1000,
	"KiB": 1024,
	"MB":  1000 * 1000,
	"MiB": 1024 * 1024,
	"GB":  1000 * 1000 * 1000,
	"GiB": 1024 * 1024 * 1024,
}

func main() {
	flag.Parse()
	size, ok := units[*unit]
	if !ok {
		flag.Usage()
		os.Exit(EXIT_USAGE)
	}

	r := rate.MakeMonitorReaderFunc(os.Stdin, 0, rateFn(size, *unit, *progress))
	defer r.Close()
	_, err := io.Copy(os.Stdout, r)
	if err != nil {
		fmt.Fprintf(os.Stderr, "io error: %v\n", err)
		os.Exit(EXIT_IO)
	}
}

func rateFn(size int, unit string, progress bool) func(r rate.Rate) {
	return func(r rate.Rate) {
		fmt.Fprintf(os.Stderr, "\r%8.4f %s/s\033[K", r.Rate/float64(size), unit)

		if progress {
			size, unit := 0, ""
			// If the rate is displayed in a base-10
			// unit, do the same for the progress,
			// and the same for base-2.
			if strings.Contains(unit, "i") {
				switch {
				case r.Total < 1024:
					size, unit = 1, "B"
				case r.Total < 1024*1024:
					size, unit = 1024, "KiB"
				case r.Total < 1024*1024*1024:
					size, unit = 1024*1024, "MiB"
				default:
					size, unit = 1024*1024*1024, "GiB"
				}
			} else {
				switch {
				case r.Total < 1000:
					size, unit = 1, "B"
				case r.Total < 1000*1000:
					size, unit = 1000, "KB"
				case r.Total < 1000*1000*1000:
					size, unit = 1000*1000, "MB"
				default:
					size, unit = 1000*1000*1000, "GB"
				}
			}
			fmt.Fprintf(os.Stderr, " (%.4f %s total)\033[K", float64(r.Total)/float64(size), unit)
		}
	}
}
<commit_msg>Switched to using docopt for arguments.<commit_after>// Copyright 2014 The Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/docopt/docopt-go"
	"github.com/synful/rate"
)

const (
	EXIT_IO = 2
)

const usage = `Usage: rate-monitor [-p] [--B | --kB | --KiB | --MB | --MiB | --GB | --GiB]

  --B           show the rate in B/s
  --kB          show the rate in kB/s
  --KiB         show the rate in KiB/s (this is the default)
  --MB          show the rate in MB/s
  --MiB         show the rate in MiB/s
  --GB          show the rate in GB/s
  --GiB         show the rate in GiB/s
  -p --progress show the total number of bytes copied in addition to the rate`

var units = map[string]int{
	"B":   1,
	"kB":  1000,
	"KiB": 1024,
	"MB":  1000 * 1000,
	"MiB": 1024 * 1024,
	"GB":  1000 * 1000 * 1000,
	"GiB": 1024 * 1024 * 1024,
}

func main() {
	args, err := docopt.Parse(usage, nil, true, "", false)
	unit, size := "KiB", units["KiB"]
	for unt, sze := range units {
		if args["--"+unt].(bool) {
			unit, size = unt, sze
			break
		}
	}

	r := rate.MakeMonitorReaderFunc(os.Stdin, 0, rateFn(size, unit, args["-p"].(bool)))
	defer r.Close()
	_, err = io.Copy(os.Stdout, r)
	if err != nil {
		fmt.Fprintf(os.Stderr, "io error: %v\n", err)
		os.Exit(EXIT_IO)
	}
}

func rateFn(size int, unit string, progress bool) func(r rate.Rate) {
	return func(r rate.Rate) {
		fmt.Fprintf(os.Stderr, "\r%8.4f %s/s\033[K", r.Rate/float64(size), unit)

		if progress {
			sizeTmp, unitTmp := 0, ""

			// If the rate is displayed in an SI unit,
			// then display the progress in SI units,
			// and likewise for IEC units.
			if strings.Contains(unit, "i") || unit == "B" {
				switch {
				case r.Total < 1024:
					sizeTmp, unitTmp = 1, "B"
				case r.Total < 1024*1024:
					sizeTmp, unitTmp = 1024, "KiB"
				case r.Total < 1024*1024*1024:
					sizeTmp, unitTmp = 1024*1024, "MiB"
				default:
					sizeTmp, unitTmp = 1024*1024*1024, "GiB"
				}
			} else {
				switch {
				case r.Total < 1000:
					sizeTmp, unitTmp = 1, "B"
				case r.Total < 1000*1000:
					sizeTmp, unitTmp = 1000, "kB"
				case r.Total < 1000*1000*1000:
					sizeTmp, unitTmp = 1000*1000, "MB"
				default:
					sizeTmp, unitTmp = 1000*1000*1000, "GB"
				}
			}
			fmt.Fprintf(os.Stderr, " (%.4f %s total)\033[K", float64(r.Total)/float64(sizeTmp), unitTmp)
		}
	}
}
<|endoftext|>


<commit_before>package sprite_sass

import (
	"fmt"
	"io/ioutil"
	"log"
	"path/filepath"

	//. "github.com/kr/pretty"
)

func init() {
	log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
}

type Parser struct {
	Input   string
	Output  []byte
	Items   []Item
	Vars    map[string]string
	Sprites map[string]ImageList
	cut     [][]int
}

// Parser reads the tokens from the lexer and performs
// conversions and/or substitutions for sprite*() calls.
//
// Parser creates a map of all variables and sprites
// (created via sprite-map calls).
func (p Parser) Start(f string) []byte {
	p.Vars = make(map[string]string)
	p.Sprites = make(map[string]ImageList)
	fvar, err := ioutil.ReadFile(f)
	if err != nil {
		panic(err)
	}
	i := string(fvar)
	p.Items, p.Input, err = parser(i, filepath.Dir(f))
	tokens := p.Items
	if err != nil {
		panic(err)
	}
	var (
		def, cmd string
	)
	for i := 0; i < len(tokens); i = i + 1 {
		token := tokens[i]
		last := i
		// Generate list of vars
		if token.Type == VAR {
			def = fmt.Sprintf("%s", token)
			val := ""
			nested := false
			for {
				i++
				token = tokens[i]
				switch token.Type {
				case LPAREN:
					nested = true
				case RPAREN:
					nested = false
				case CMD:
					cmd = fmt.Sprintf("%s", token)
					val += cmd
				case FILE:
					i = p.File(cmd, i, last)
					def = ""
					cmd = ""
				case SUB:
					// Can this ever happen, do we care?
					fmt.Println("SUB")
				default:
					//fmt.Printf("Default: %s\n", token)
					val += fmt.Sprintf("%s", token)
				}

				if !nested && tokens[i].Type != CMD {
					break
				}
			}
			if def != "" {
				p.Vars[def] = val
			}
			//Replace subsitution tokens
		} else if token.Type == SUB {
			if cmd == "sprite" {
				//Capture sprite
				sprite := p.Sprites[fmt.Sprintf("%s", token)]
				//Capture filename
				i++
				name := fmt.Sprintf("%s", tokens[i])
				tokens[i].Value = sprite.CSS(name)
				tokens[i].Write = true
				tokens = append(tokens[:i-3], tokens[i:]...)
				i = i - 3
				cmd = ""
			} else {
				tokens[i].Value = p.Vars[token.Value]
			}
		} else if token.Type == CMD {
			cmd = fmt.Sprintf("%s", token)
		}
	}
	p.Output = process(p.Input, p.Items, 0)

	return p.Output
}

func (p Parser) Cut() {
}

func (p Parser) Mark(start, end int) {
	p.cut = append(p.cut, []int{start, end})
}

func (p Parser) File(cmd string, pos, last int) int {
	item := p.Items[pos]
	// Find the next newline, failing that find the semicolon
	first := p.Items[last]

	i := pos

	if cmd == "sprite-map" {
		for ; p.Items[i].Type != RPAREN; i++ {
		}
		i = i - 1
		// Verify that the statement ends with semicolon
		interest := p.Items[i+2]
		// Mark this area for deletion, since doing so now would
		// invalidate all subsequent tokens
		p.Mark(first.Pos, interest.Pos)
		//p.Input = p.Input[:first.Pos] + p.Input[interest.Pos:]

		imgs := ImageList{}
		glob := fmt.Sprintf("%s", item)
		name := fmt.Sprintf("%s", p.Items[last])
		imgs.Decode(glob)
		imgs.Vertical = true
		imgs.Combine()
		p.Sprites[name] = imgs
		//TODO: Generate filename
		//imgs.Export("generated.png")
	}
	return i
}

func process(in string, items []Item, pos int) []byte {

	var out []byte
	l := len(items)

	if pos >= len(in) {
		return []byte("")
	}

	if items[0].Type == CMD && items[0].Value == "sprite" {
		i := 1
		//out = append(out, items[0].Value...)
		//Skip to semicolon
		for ; items[i].Write || i > l; i++ {
		}
		return append(out, process(in, items[i:], items[i].Pos)...)
	}

	if items[0].Write {
		i := 1
		out = append(out, items[0].Value...)
		//Skip to semicolon
		for ; items[i].Type != SEMIC || i > l; i++ {
		}
		return append(out, process(in, items[i:], pos)...)
	}

	// TODO: There's an error where items[1] has an invalid
	// position.
	if l > 1 && items[1].Pos > items[0].Pos {

		if items[1].Write {
			out = append(out, items[0].Value...)
			out = append(out, ':', ' ')
		} else {
			out = append(out, in[items[0].Pos:items[1].Pos]...)
		}
		out = append(out, process(in, items[1:], pos)...)
	} else {
		out = append(out, in[items[0].Pos:]...)
	}

	return out
}

// parser recrusively resolves all imports and tokenizes the
// input string
func parser(input, path string) ([]Item, string, error) {

	var (
		status    []Item
		importing bool
		output    []byte
		pos       int
		last      *Item
	)

	lex := New(func(lex *Lexer) StateFn {
		return lex.Action()
	}, input)

	for {
		item := lex.Next()
		err := item.Error()

		if err != nil {
			return nil, string(output), fmt.Errorf("Error: %v (pos %d)", err, item.Pos)
		}
		if item.Type == ItemEOF {
			output = append(output, input[pos:]...)
			return status, string(output), nil
		} else if item.Type == IMPORT {
			output = append(output, input[pos:item.Pos]...)
			last = item
			importing = true
		} else {
			if importing {
				//Load and retrieve all tokens from imported file
				path := fmt.Sprintf(
					"%s/_%s.scss",
					path, *item)

				file, err := ioutil.ReadFile(path)
				if err != nil {
					fullpath, _ := filepath.Abs(path)
					panic("Cannot import path: " + fullpath)
				}
				//pos = item.Pos + len(item.Value) + 2 //Adjust for ";
				//Eat the semicolon
				item := lex.Next()
				pos = item.Pos + len(item.Value)
				if item.Type != SEMIC {
					panic("@import must be followed by ;")
				}
				//pos = item.Pos + len(item.Value)
				moreTokens, moreOutput, err := parser(string(file),
					filepath.Dir(path))
				// Lexer needs to be adjusted for current
				// position of end of @import
				for i, _ := range moreTokens {
					moreTokens[i].Pos += last.Pos
				}

				if err != nil {
					panic(err)
				}
				output = append(output, moreOutput...)
				status = append(status, moreTokens...)
				importing = false
			} else {
				output = append(output, input[pos:item.Pos]...)
				pos = item.Pos
				status = append(status, *item)
			}
		}
	}

}
<commit_msg>Removing of illegal libsass variables<commit_after>package sprite_sass

import (
	"fmt"
	"io/ioutil"
	"log"
	"path/filepath"

	//. "github.com/kr/pretty"
)

func init() {
	log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
}

type Parser struct {
	Input   string
	Output  []byte
	Items   []Item
	Vars    map[string]string
	Sprites map[string]ImageList
	cut     [][]int
}

// Parser reads the tokens from the lexer and performs
// conversions and/or substitutions for sprite*() calls.
//
// Parser creates a map of all variables and sprites
// (created via sprite-map calls).
func (p Parser) Start(f string) []byte {
	p.Vars = make(map[string]string)
	p.Sprites = make(map[string]ImageList)
	fvar, err := ioutil.ReadFile(f)
	if err != nil {
		panic(err)
	}
	i := string(fvar)
	p.Items, p.Input, err = parser(i, filepath.Dir(f))
	tokens := p.Items
	if err != nil {
		panic(err)
	}
	var (
		def, cmd string
	)
	for i := 0; i < len(tokens); i = i + 1 {
		token := tokens[i]
		last := i
		// Generate list of vars
		if token.Type == VAR {
			def = fmt.Sprintf("%s", token)
			val := ""
			nested := false
			for {
				i++
				token = tokens[i]
				switch token.Type {
				case LPAREN:
					nested = true
				case RPAREN:
					nested = false
				case CMD:
					cmd = fmt.Sprintf("%s", token)
					val += cmd
				case FILE:
					i = p.File(cmd, i, last)
					def = ""
					cmd = ""
				case SUB:
					// Can this ever happen, do we care?
					fmt.Println("SUB")
				default:
					//fmt.Printf("Default: %s\n", token)
					val += fmt.Sprintf("%s", token)
				}

				if !nested && tokens[i].Type != CMD {
					break
				}
			}
			if def != "" {
				p.Vars[def] = val
			}
			//Replace subsitution tokens
		} else if token.Type == SUB {
			if cmd == "sprite" {
				//Capture sprite
				sprite := p.Sprites[fmt.Sprintf("%s", token)]
				//Capture filename
				i++
				name := fmt.Sprintf("%s", tokens[i])
				tokens[i].Value = sprite.CSS(name)
				tokens[i].Write = true
				tokens = append(tokens[:i-3], tokens[i:]...)
				i = i - 3
				cmd = ""
			} else {
				tokens[i].Value = p.Vars[token.Value]
			}
		} else if token.Type == CMD {
			cmd = fmt.Sprintf("%s", token)
		}
	}
	p.Output = process(p.Input, p.Items, 0)
	p.Cut()
	return p.Output
}

// Iterates through the p.cut slice deleting specified
// portions of the output array.
func (p *Parser) Cut() {
	shift := 0
	for _, c := range p.cut {
		begin := c[0] - shift
		end := c[1] - shift
		shift += c[1] - c[0]
		p.Output = append(p.Output[:begin], p.Output[end:]...)
	}
}

func (p *Parser) Mark(start, end int) {
	p.cut = append(p.cut, []int{start, end})
}

func (p *Parser) File(cmd string, pos, last int) int {
	item := p.Items[pos]
	// Find the next newline, failing that find the semicolon
	first := p.Items[last]

	i := pos

	if cmd == "sprite-map" {
		for ; p.Items[i].Type != RPAREN; i++ {
		}
		i = i - 1
		// Verify that the statement ends with semicolon
		interest := p.Items[i+3]
		// Mark this area for deletion, since doing so now would
		// invalidate all subsequent tokens
		p.Mark(first.Pos, interest.Pos)
		//p.Input = p.Input[:first.Pos] + p.Input[interest.Pos:]

		imgs := ImageList{}
		glob := fmt.Sprintf("%s", item)
		name := fmt.Sprintf("%s", p.Items[last])
		imgs.Decode(glob)
		imgs.Vertical = true
		imgs.Combine()
		p.Sprites[name] = imgs
		//TODO: Generate filename
		//imgs.Export("generated.png")
	}
	return i
}

func process(in string, items []Item, pos int) []byte {

	var out []byte
	l := len(items)

	if pos >= len(in) {
		return []byte("")
	}

	if items[0].Type == CMD && items[0].Value == "sprite" {
		i := 1
		//out = append(out, items[0].Value...)
		//Skip to semicolon
		for ; items[i].Write || i > l; i++ {
		}
		return append(out, process(in, items[i:], items[i].Pos)...)
	}

	if items[0].Write {
		i := 1
		out = append(out, items[0].Value...)
		//Skip to semicolon
		for ; items[i].Type != SEMIC || i > l; i++ {
		}
		return append(out, process(in, items[i:], pos)...)
	}

	// TODO: There's an error where items[1] has an invalid
	// position.
	if l > 1 && items[1].Pos > items[0].Pos {

		if items[1].Write {
			out = append(out, items[0].Value...)
			out = append(out, ':', ' ')
		} else {
			out = append(out, in[items[0].Pos:items[1].Pos]...)
		}
		out = append(out, process(in, items[1:], pos)...)
	} else {
		out = append(out, in[items[0].Pos:]...)
	}

	return out
}

// parser recrusively resolves all imports and tokenizes the
// input string
func parser(input, path string) ([]Item, string, error) {

	var (
		status    []Item
		importing bool
		output    []byte
		pos       int
		last      *Item
	)

	lex := New(func(lex *Lexer) StateFn {
		return lex.Action()
	}, input)

	for {
		item := lex.Next()
		err := item.Error()

		if err != nil {
			return nil, string(output), fmt.Errorf("Error: %v (pos %d)", err, item.Pos)
		}
		if item.Type == ItemEOF {
			output = append(output, input[pos:]...)
			return status, string(output), nil
		} else if item.Type == IMPORT {
			output = append(output, input[pos:item.Pos]...)
			last = item
			importing = true
		} else {
			if importing {
				//Load and retrieve all tokens from imported file
				path := fmt.Sprintf(
					"%s/_%s.scss",
					path, *item)

				file, err := ioutil.ReadFile(path)
				if err != nil {
					fullpath, _ := filepath.Abs(path)
					panic("Cannot import path: " + fullpath)
				}
				//pos = item.Pos + len(item.Value) + 2 //Adjust for ";
				//Eat the semicolon
				item := lex.Next()
				pos = item.Pos + len(item.Value)
				if item.Type != SEMIC {
					panic("@import must be followed by ;")
				}
				//pos = item.Pos + len(item.Value)
				moreTokens, moreOutput, err := parser(string(file),
					filepath.Dir(path))
				// Lexer needs to be adjusted for current
				// position of end of @import
				for i, _ := range moreTokens {
					moreTokens[i].Pos += last.Pos
				}

				if err != nil {
					panic(err)
				}
				output = append(output, moreOutput...)
				status = append(status, moreTokens...)
				importing = false
			} else {
				output = append(output, input[pos:item.Pos]...)
				pos = item.Pos
				status = append(status, *item)
			}
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"log"
	"log/syslog"
	"net/smtp"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/johansundell/cocapi"
)

var db *sql.DB
var mysqlUser, mysqlPass, mysqlDb, mysqlHost string
var queryInsertUpdateMember = `INSERT INTO members (tag, name, created, last_updated, active) VALUES (?, ?, null, null, 1) ON DUPLICATE KEY UPDATE member_id=LAST_INSERT_ID(member_id), last_updated = NOW(), active = 1`
var isCocUnderUpdate bool
var failedTries int

func init() {

	mysqlDb = "cocsniffer"
	mysqlHost = os.Getenv("MYSQL_COC_HOST")
	mysqlUser = os.Getenv("MYSQL_USER")
	mysqlPass = os.Getenv("MYSQL_PASS")
}

func main() {
	useSyslog := flag.Bool("syslog", false, "Use syslog")
	flag.Parse()
	if *useSyslog {
		logwriter, e := syslog.New(syslog.LOG_NOTICE, "cocsniffer")
		if e == nil {
			log.SetOutput(logwriter)
		}
	}
	db, _ = sql.Open("mysql", mysqlUser+":"+mysqlPass+"@tcp("+mysqlHost+":3306)/"+mysqlDb)
	defer db.Close()

	isCocUnderUpdate = false
	failedTries = 0
	getMembersData()
	ticker := time.NewTicker(1 * time.Minute)
	quit := make(chan struct{})
	go func() {
		for {
			select {
			case <-ticker.C:
				getMembersData()
			case <-quit:
				ticker.Stop()
				return
			}
		}
	}()

	// Wait for SIGINT and SIGTERM (HIT CTRL-C)
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	log.Println(<-ch)

	close(quit)
	log.Println("Bye ;)")
}

func getMembersData() {
	members, err := cocapi.GetMemberInfo()
	if err != nil {
		reportError(err)
		return
	}

	if isCocUnderUpdate {
		isCocUnderUpdate = false
		sendEmail("johan@pixpro.net", "johan@sundell.com", "COC Alert", "Servers are up again")
	}
	failedTries = 0

	var ids = make([]string, 0)
	for _, m := range members.Items {
		if result, err := db.Exec(queryInsertUpdateMember, m.Tag, m.Name); err != nil {
			log.Println(err)
		} else {
			if id, err := result.LastInsertId(); err != nil {
				log.Println(err)
			} else {
				ids = append(ids, strconv.Itoa(int(id)))
			}
		}
	}
	db.Exec("UPDATE members SET exited = NOW() WHERE member_id NOT IN (" + strings.Join(ids, ", ") + ") AND active = 1")
	db.Exec("UPDATE members SET active = 0 WHERE member_id NOT IN (" + strings.Join(ids, ", ") + ")")
	log.Println("done members func")
}

func reportError(err error) {
	switch t := err.(type) {
	case *cocapi.ServerError:
		if t.ErrorCode == 503 {
			failedTries++
			if failedTries > 3 {
				if !isCocUnderUpdate {
					isCocUnderUpdate = true
					sendEmail("johan@pixpro.net", "johan@sundell.com", "COC Alert", "Servers under update")
				}
			}
		}
		break
	default:
		log.Println("Fatal error coc:", t)
		break
	}
}

func sendEmail(to, from, subject, message string) bool {
	body := "To: " + to + "\r\nSubject: " + subject + "\r\n\r\n" + message
	if err := smtp.SendMail("127.0.0.1:25", nil, from, []string{to}, []byte(body)); err != nil {
		log.Println(err)
		return false
	}
	return true
}
<commit_msg>Fixed email and upgarde member alerts<commit_after>package main

import (
	"database/sql"
	"flag"
	"log"
	"log/syslog"
	"net/smtp"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/johansundell/cocapi"
)

var db *sql.DB
var mysqlUser, mysqlPass, mysqlDb, mysqlHost string
var queryInsertUpdateMember = `INSERT INTO members (tag, name, created, last_updated, active) VALUES (?, ?, null, null, 1) ON DUPLICATE KEY UPDATE member_id=LAST_INSERT_ID(member_id), last_updated = NOW(), active = 1`
var isCocUnderUpdate bool
var failedTries int
var emailTo, emailFrom string

func init() {

	mysqlDb = "cocsniffer"
	mysqlHost = os.Getenv("MYSQL_COC_HOST")
	mysqlUser = os.Getenv("MYSQL_USER")
	mysqlPass = os.Getenv("MYSQL_PASS")

	emailTo = os.Getenv("EMAIL_TO")
	emailFrom = os.Getenv("EMAIL_FROM")
}

func main() {
	useSyslog := flag.Bool("syslog", false, "Use syslog")
	flag.Parse()
	if *useSyslog {
		logwriter, e := syslog.New(syslog.LOG_NOTICE, "cocsniffer")
		if e == nil {
			log.SetOutput(logwriter)
		}
	}
	db, _ = sql.Open("mysql", mysqlUser+":"+mysqlPass+"@tcp("+mysqlHost+":3306)/"+mysqlDb)
	defer db.Close()

	isCocUnderUpdate = false
	failedTries = 0
	getMembersData()
	ticker := time.NewTicker(1 * time.Minute)
	quit := make(chan struct{})
	go func() {
		for {
			select {
			case <-ticker.C:
				getMembersData()
			case <-quit:
				ticker.Stop()
				return
			}
		}
	}()

	// Wait for SIGINT and SIGTERM (HIT CTRL-C)
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	log.Println(<-ch)

	close(quit)
	log.Println("Bye ;)")
}

func getMembersData() {
	members, err := cocapi.GetMemberInfo()
	if err != nil {
		reportError(err)
		return
	}

	if isCocUnderUpdate {
		isCocUnderUpdate = false
		sendEmail("COC Alert", "Servers are up again")
	}
	failedTries = 0

	var ids = make([]string, 0)
	for _, m := range members.Items {
		if result, err := db.Exec(queryInsertUpdateMember, m.Tag, m.Name); err != nil {
			log.Println(err)
		} else {
			if id, err := result.LastInsertId(); err != nil {
				log.Println(err)
			} else {
				ids = append(ids, strconv.Itoa(int(id)))
			}
		}
		if m.Role == "member" && m.Donations >= 1000 {
			log.Println("Found member that should be upgraded", m.Name)
			var alerted int
			db.QueryRow("SELECT alert_sent_donations FROM members WHERE tag = ?", m.Tag).Scan(&alerted)
			if alerted == 0 {
				sendEmail("Member "+m.Name+" should be upgraded", "Member "+m.Name+" should be upgraded")
				db.Exec("UPDATE members SET alert_sent_donations = 1 WHERE tag = ?", m.Tag)
			}
		}
	}
	db.Exec("UPDATE members SET exited = NOW() WHERE member_id NOT IN (" + strings.Join(ids, ", ") + ") AND active = 1")
	db.Exec("UPDATE members SET active = 0 WHERE member_id NOT IN (" + strings.Join(ids, ", ") + ")")
	//log.Println("done members func")
}

func reportError(err error) {
	switch t := err.(type) {
	case *cocapi.ServerError:
		if t.ErrorCode == 503 {
			failedTries++
			if failedTries > 3 {
				if !isCocUnderUpdate {
					isCocUnderUpdate = true
					sendEmail("COC Alert", "Servers under update")
				}
			}
		}
		break
	default:
		log.Println("Fatal error coc:", t)
		break
	}
}

func sendEmail(subject, message string) bool {
	body := "To: " + emailTo + "\r\nSubject: " + subject + "\r\n\r\n" + message
	if err := smtp.SendMail("127.0.0.1:25", nil, emailFrom, []string{emailTo}, []byte(body)); err != nil {
		log.Println(err)
		return false
	}
	return true
}
<|endoftext|>