<commit_before>package slack

import (
	"context"
	"net/url"
	"strconv"
)

const (
	DEFAULT_STARS_USER  = ""
	DEFAULT_STARS_COUNT = 100
	DEFAULT_STARS_PAGE  = 1
)

type StarsParameters struct {
	User  string
	Count int
	Page  int
}

type StarredItem Item

type listResponseFull struct {
	Items  []Item `json:"items"`
	Paging `json:"paging"`
	SlackResponse
}

// NewStarsParameters initialises StarsParameters with default values
func NewStarsParameters() StarsParameters {
	return StarsParameters{
		User:  DEFAULT_STARS_USER,
		Count: DEFAULT_STARS_COUNT,
		Page:  DEFAULT_STARS_PAGE,
	}
}

// AddStar stars an item in a channel
func (api *Client) AddStar(channel string, item ItemRef) error {
	return api.AddStarContext(context.Background(), channel, item)
}

// AddStarContext stars an item in a channel with a custom context
func (api *Client) AddStarContext(ctx context.Context, channel string, item ItemRef) error {
	values := url.Values{
		"channel": {channel},
		"token":   {api.token},
	}
	if item.Timestamp != "" {
		values.Set("timestamp", item.Timestamp)
	}
	if item.File != "" {
		values.Set("file", item.File)
	}
	if item.Comment != "" {
		values.Set("file_comment", item.Comment)
	}

	response := &SlackResponse{}
	if err := api.postMethod(ctx, "stars.add", values, response); err != nil {
		return err
	}

	return response.Err()
}

// RemoveStar removes a starred item from a channel
func (api *Client) RemoveStar(channel string, item ItemRef) error {
	return api.RemoveStarContext(context.Background(), channel, item)
}

// RemoveStarContext removes a starred item from a channel with a custom context
func (api *Client) RemoveStarContext(ctx context.Context, channel string, item ItemRef) error {
	values := url.Values{
		"channel": {channel},
		"token":   {api.token},
	}
	if item.Timestamp != "" {
		values.Set("timestamp", item.Timestamp)
	}
	if item.File != "" {
		values.Set("file", item.File)
	}
	if item.Comment != "" {
		values.Set("file_comment", item.Comment)
	}

	response := &SlackResponse{}
	if err := api.postMethod(ctx, "stars.remove", values, response); err != nil {
		return err
	}

	return response.Err()
}

// ListStars returns information about the stars a user added
func (api *Client) ListStars(params StarsParameters) ([]Item, *Paging, error) {
	return api.ListStarsContext(context.Background(), params)
}

// ListStarsContext returns information about the stars a user added with a custom context
func (api *Client) ListStarsContext(ctx context.Context, params StarsParameters) ([]Item, *Paging, error) {
	values := url.Values{
		"token": {api.token},
	}
	if params.User != DEFAULT_STARS_USER {
		values.Add("user", params.User)
	}
	if params.Count != DEFAULT_STARS_COUNT {
		values.Add("count", strconv.Itoa(params.Count))
	}
	if params.Page != DEFAULT_STARS_PAGE {
		values.Add("page", strconv.Itoa(params.Page))
	}

	response := &listResponseFull{}
	err := api.postMethod(ctx, "stars.list", values, response)
	if err != nil {
		return nil, nil, err
	}

	if err := response.Err(); err != nil {
		return nil, nil, err
	}

	return response.Items, &response.Paging, nil
}

// GetStarred returns a list of StarredItem items.
//
// The user then has to iterate over them and figure out what they should
// be looking at according to what is in the Type.
//    for _, item := range items {
//        switch c.Type {
//        case "file_comment":
//            log.Println(c.Comment)
//        case "file":
//             ...
//
//    }
// This function still exists to maintain backwards compatibility.
// I exposed it as returning []StarredItem, so it shall stay as StarredItem
func (api *Client) GetStarred(params StarsParameters) ([]StarredItem, *Paging, error) {
	return api.GetStarredContext(context.Background(), params)
}

// GetStarredContext returns a list of StarredItem items with a custom context
//
// For more details see GetStarred
func (api *Client) GetStarredContext(ctx context.Context, params StarsParameters) ([]StarredItem, *Paging, error) {
	items, paging, err := api.ListStarsContext(ctx, params)
	if err != nil {
		return nil, nil, err
	}
	starredItems := make([]StarredItem, len(items))
	for i, item := range items {
		starredItems[i] = StarredItem(item)
	}
	return starredItems, paging, nil
}
<commit_msg>add pagination support for ListStars<commit_after>package slack

import (
	"context"
	"net/url"
	"strconv"
)

const (
	DEFAULT_STARS_USER  = ""
	DEFAULT_STARS_COUNT = 100
	DEFAULT_STARS_PAGE  = 1
)

type StarsParameters struct {
	User  string
	Count int
	Page  int
}

type StarredItem Item

type listResponseFull struct {
	Items  []Item `json:"items"`
	Paging `json:"paging"`
	SlackResponse
}

// NewStarsParameters initialises StarsParameters with default values
func NewStarsParameters() StarsParameters {
	return StarsParameters{
		User:  DEFAULT_STARS_USER,
		Count: DEFAULT_STARS_COUNT,
		Page:  DEFAULT_STARS_PAGE,
	}
}

// AddStar stars an item in a channel
func (api *Client) AddStar(channel string, item ItemRef) error {
	return api.AddStarContext(context.Background(), channel, item)
}

// AddStarContext stars an item in a channel with a custom context
func (api *Client) AddStarContext(ctx context.Context, channel string, item ItemRef) error {
	values := url.Values{
		"channel": {channel},
		"token":   {api.token},
	}
	if item.Timestamp != "" {
		values.Set("timestamp", item.Timestamp)
	}
	if item.File != "" {
		values.Set("file", item.File)
	}
	if item.Comment != "" {
		values.Set("file_comment", item.Comment)
	}

	response := &SlackResponse{}
	if err := api.postMethod(ctx, "stars.add", values, response); err != nil {
		return err
	}

	return response.Err()
}

// RemoveStar removes a starred item from a channel
func (api *Client) RemoveStar(channel string, item ItemRef) error {
	return api.RemoveStarContext(context.Background(), channel, item)
}

// RemoveStarContext removes a starred item from a channel with a custom context
func (api *Client) RemoveStarContext(ctx context.Context, channel string, item ItemRef) error {
	values := url.Values{
		"channel": {channel},
		"token":   {api.token},
	}
	if item.Timestamp != "" {
		values.Set("timestamp", item.Timestamp)
	}
	if item.File != "" {
		values.Set("file", item.File)
	}
	if item.Comment != "" {
		values.Set("file_comment", item.Comment)
	}

	response := &SlackResponse{}
	if err := api.postMethod(ctx, "stars.remove", values, response); err != nil {
		return err
	}

	return response.Err()
}

// ListStars returns information about the stars a user added
func (api *Client) ListStars(params StarsParameters) ([]Item, *Paging, error) {
	return api.ListStarsContext(context.Background(), params)
}

// ListStarsContext returns information about the stars a user added with a custom context
func (api *Client) ListStarsContext(ctx context.Context, params StarsParameters) ([]Item, *Paging, error) {
	values := url.Values{
		"token": {api.token},
	}
	if params.User != DEFAULT_STARS_USER {
		values.Add("user", params.User)
	}
	if params.Count != DEFAULT_STARS_COUNT {
		values.Add("count", strconv.Itoa(params.Count))
	}
	if params.Page != DEFAULT_STARS_PAGE {
		values.Add("page", strconv.Itoa(params.Page))
	}

	response := &listResponseFull{}
	err := api.postMethod(ctx, "stars.list", values, response)
	if err != nil {
		return nil, nil, err
	}

	if err := response.Err(); err != nil {
		return nil, nil, err
	}

	return response.Items, &response.Paging, nil
}

// GetStarred returns a list of StarredItem items.
//
// The user then has to iterate over them and figure out what they should
// be looking at according to what is in the Type.
//    for _, item := range items {
//        switch c.Type {
//        case "file_comment":
//            log.Println(c.Comment)
//        case "file":
//             ...
//
//    }
// This function still exists to maintain backwards compatibility.
// I exposed it as returning []StarredItem, so it shall stay as StarredItem
func (api *Client) GetStarred(params StarsParameters) ([]StarredItem, *Paging, error) {
	return api.GetStarredContext(context.Background(), params)
}

// GetStarredContext returns a list of StarredItem items with a custom context
//
// For more details see GetStarred
func (api *Client) GetStarredContext(ctx context.Context, params StarsParameters) ([]StarredItem, *Paging, error) {
	items, paging, err := api.ListStarsContext(ctx, params)
	if err != nil {
		return nil, nil, err
	}
	starredItems := make([]StarredItem, len(items))
	for i, item := range items {
		starredItems[i] = StarredItem(item)
	}
	return starredItems, paging, nil
}

type listResponsePaginated struct {
	Items []Item `json:"items"`
	SlackResponse
	Metadata ResponseMetadata `json:"response_metadata"`
}

// StarredItemPagination allows for paginating over the starred items
type StarredItemPagination struct {
	Items        []Item
	limit        int
	previousResp *ResponseMetadata
	c            *Client
}

// ListStarsOption options for the GetUsers method call.
type ListStarsOption func(*StarredItemPagination)

// ListStarredAll returns the complete list of starred items
func (api *Client) ListStarredAll() ([]Item, error) {
	return api.ListStarsPaginatedContext(context.Background())
}

// ListStarsPaginatedContext returns the list of users (with their detailed information) with a custom context
func (api *Client) ListStarsPaginatedContext(ctx context.Context) (results []Item, err error) {
	var p StarredItemPagination

	for p = api.ListStarsPaginated(); !p.done(err); p, err = p.next(ctx) {
		results = append(results, p.Items...)
	}

	return results, p.failure(err)
}

// ListStarsPaginated fetches users in a paginated fashion, see ListStarsPaginationContext for usage.
func (api *Client) ListStarsPaginated(options ...ListStarsOption) StarredItemPagination {
	return newStarPagination(api, options...)
}

func newStarPagination(c *Client, options ...ListStarsOption) (sip StarredItemPagination) {
	sip = StarredItemPagination{
		c:     c,
		limit: 200, // per slack api documentation.
	}

	for _, opt := range options {
		opt(&sip)
	}

	return sip
}

// done checks if the pagination has completed
func (StarredItemPagination) done(err error) bool {
	return err == errPaginationComplete
}

// done checks if pagination failed.
func (t StarredItemPagination) failure(err error) error {
	if t.done(err) {
		return nil
	}

	return err
}

// next gets the next list of starred items based on the cursor value
func (t StarredItemPagination) next(ctx context.Context) (_ StarredItemPagination, err error) {
	var (
		resp *listResponsePaginated
	)

	if t.c == nil || (t.previousResp != nil && t.previousResp.Cursor == "") {
		return t, errPaginationComplete
	}

	t.previousResp = t.previousResp.initialize()

	values := url.Values{
		"limit":  {strconv.Itoa(t.limit)},
		"token":  {t.c.token},
		"cursor": {t.previousResp.Cursor},
	}

	if err = t.c.postMethod(ctx, "stars.list", values, &resp); err != nil {
		return t, err
	}

	t.previousResp = &resp.Metadata
	t.Items = resp.Items

	return t, nil
}
<|endoftext|>


<commit_before>package agollo

import (
	"github.com/zouyx/agollo/v3/agcache"
	"github.com/zouyx/agollo/v3/component"
	"github.com/zouyx/agollo/v3/component/log"
	"github.com/zouyx/agollo/v3/component/notify"
	"github.com/zouyx/agollo/v3/component/serverlist"
	"github.com/zouyx/agollo/v3/env"
	"github.com/zouyx/agollo/v3/env/config"
	"github.com/zouyx/agollo/v3/env/file"
	_ "github.com/zouyx/agollo/v3/env/file/json"
	"github.com/zouyx/agollo/v3/extension"
	"github.com/zouyx/agollo/v3/loadbalance/roundrobin"
	"github.com/zouyx/agollo/v3/storage"
)

var (
	initAppConfigFunc func() (*config.AppConfig, error)
)

func init() {
	roundrobin.InitLoadBalance()
}

//InitCustomConfig init config by custom
func InitCustomConfig(loadAppConfig func() (*config.AppConfig, error)) {
	initAppConfigFunc = loadAppConfig
}

//start apollo
func Start() error {
	return startAgollo()
}

//SetLogger 设置自定义logger组件
func SetBackupFileHandler(file file.FileHandler) {
	if file != nil {
		extension.SetFileHandler(file)
	}
}

//SetLogger 设置自定义logger组件
func SetLogger(loggerInterface log.LoggerInterface) {
	if loggerInterface != nil {
		log.InitLogger(loggerInterface)
	}
}

//SetCache 设置自定义cache组件
func SetCache(cacheFactory agcache.CacheFactory) {
	if cacheFactory != nil {
		agcache.UseCacheFactory(cacheFactory)
		storage.InitConfigCache()
	}
}

func startAgollo() error {
	// 有了配置之后才能进行初始化
	if err := env.InitConfig(initAppConfigFunc); err != nil {
		return err
	}

	notify.InitAllNotifications(nil)
	serverlist.InitSyncServerIPList()

	//first sync
	if err := notify.SyncConfigs(); err != nil {
		return err
	}
	log.Debug("init notifySyncConfigServices finished")

	//start long poll sync config
	go component.StartRefreshConfig(&notify.ConfigComponent{})

	log.Info("agollo start finished ! ")

	return nil
}
<commit_msg>modify extension<commit_after>package agollo

import (
	"github.com/zouyx/agollo/v3/agcache"
	"github.com/zouyx/agollo/v3/component"
	"github.com/zouyx/agollo/v3/component/log"
	"github.com/zouyx/agollo/v3/component/notify"
	"github.com/zouyx/agollo/v3/component/serverlist"
	"github.com/zouyx/agollo/v3/env"
	"github.com/zouyx/agollo/v3/env/config"
	"github.com/zouyx/agollo/v3/env/file"
	_ "github.com/zouyx/agollo/v3/env/file/json"
	"github.com/zouyx/agollo/v3/extension"
	"github.com/zouyx/agollo/v3/loadbalance/roundrobin"
	"github.com/zouyx/agollo/v3/storage"
)

var (
	initAppConfigFunc func() (*config.AppConfig, error)
)

func init() {
	roundrobin.InitLoadBalance()
}

//InitCustomConfig init config by custom
func InitCustomConfig(loadAppConfig func() (*config.AppConfig, error)) {
	initAppConfigFunc = loadAppConfig
}

//start apollo
func Start() error {
	return startAgollo()
}

//SetBackupFileHandler 设置自定义备份文件处理组件
func SetBackupFileHandler(file file.FileHandler) {
	if file != nil {
		extension.SetFileHandler(file)
	}
}

//SetLogger 设置自定义logger组件
func SetLogger(loggerInterface log.LoggerInterface) {
	if loggerInterface != nil {
		log.InitLogger(loggerInterface)
	}
}

//SetCache 设置自定义cache组件
func SetCache(cacheFactory agcache.CacheFactory) {
	if cacheFactory != nil {
		agcache.UseCacheFactory(cacheFactory)
		storage.InitConfigCache()
	}
}

func startAgollo() error {
	// 有了配置之后才能进行初始化
	if err := env.InitConfig(initAppConfigFunc); err != nil {
		return err
	}

	notify.InitAllNotifications(nil)
	serverlist.InitSyncServerIPList()

	//first sync
	if err := notify.SyncConfigs(); err != nil {
		return err
	}
	log.Debug("init notifySyncConfigServices finished")

	//start long poll sync config
	go component.StartRefreshConfig(&notify.ConfigComponent{})

	log.Info("agollo start finished ! ")

	return nil
}
<|endoftext|>


<commit_before>// +build linux

package main

import (
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/coreos/go-systemd/activation"
	"github.com/opencontainers/runc/libcontainer"
	"github.com/opencontainers/specs/specs-go"
)

// default action is to start a container
var startCommand = cli.Command{
	Name:  "start",
	Usage: "create and run a container",
	ArgsUsage: `<container-id>

Where "<container-id>" is your name for the instance of the container that you
are starting. The name you provide for the container instance must be unique on
your host.`,
	Description: `The start command creates an instance of a container for a bundle. The bundle
is a directory with a specification file named "` + specConfig + `" and a root
filesystem.

The specification file includes an args parameter. The args parameter is used
to specify command(s) that get run when the container is started. To change the
command(s) that get executed on start, edit the args parameter of the spec. See
"runc spec --help" for more explanation.`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "bundle, b",
			Value: "",
			Usage: `path to the root of the bundle directory, defaults to the current directory`,
		},
		cli.StringFlag{
			Name:  "console",
			Value: "",
			Usage: "specify the pty slave path for use with the container",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.BoolFlag{
			Name:  "no-subreaper",
			Usage: "disable the use of the subreaper used to reap reparented processes",
		},
	},
	Action: func(context *cli.Context) {
		bundle := context.String("bundle")
		if bundle != "" {
			if err := os.Chdir(bundle); err != nil {
				fatal(err)
			}
		}
		spec, err := loadSpec(specConfig)
		if err != nil {
			fatal(err)
		}

		notifySocket := os.Getenv("NOTIFY_SOCKET")
		if notifySocket != "" {
			setupSdNotify(spec, notifySocket)
		}

		if os.Geteuid() != 0 {
			fatalf("runc should be run as root")
		}

		status, err := startContainer(context, spec)
		if err != nil {
			fatal(err)
		}
		// exit with the container's exit status so any external supervisor is
		// notified of the exit with the correct exit status.
		os.Exit(status)
	},
}

var initCommand = cli.Command{
	Name:  "init",
	Usage: `initialize the namespaces and launch the process (do not call it outside of runc)`,
	Action: func(context *cli.Context) {
		runtime.GOMAXPROCS(1)
		runtime.LockOSThread()
		factory, _ := libcontainer.New("")
		if err := factory.StartInitialization(); err != nil {
			// as the error is sent back to the parent there is no need to log
			// or write it to stderr because the parent process will handle this
			os.Exit(1)
		}
		panic("libcontainer: container init failed to exec")
	},
}

func startContainer(context *cli.Context, spec *specs.Spec) (int, error) {
	id := context.Args().First()
	if id == "" {
		return -1, errEmptyID
	}
	container, err := createContainer(context, id, spec)
	if err != nil {
		return -1, err
	}
	detach := context.Bool("detach")
	// Support on-demand socket activation by passing file descriptors into the container init process.
	listenFDs := []*os.File{}
	if os.Getenv("LISTEN_FDS") != "" {
		listenFDs = activation.Files(false)
	}
	r := &runner{
		enableSubreaper: !context.Bool("no-subreaper"),
		shouldDestroy:   true,
		container:       container,
		listenFDs:       listenFDs,
		console:         context.String("console"),
		detach:          detach,
		pidFile:         context.String("pid-file"),
	}
	return r.run(&spec.Process)
}
<commit_msg>Move lockthread to package level<commit_after>// +build linux

package main

import (
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/coreos/go-systemd/activation"
	"github.com/opencontainers/runc/libcontainer"
	"github.com/opencontainers/specs/specs-go"
)

// default action is to start a container
var startCommand = cli.Command{
	Name:  "start",
	Usage: "create and run a container",
	ArgsUsage: `<container-id>

Where "<container-id>" is your name for the instance of the container that you
are starting. The name you provide for the container instance must be unique on
your host.`,
	Description: `The start command creates an instance of a container for a bundle. The bundle
is a directory with a specification file named "` + specConfig + `" and a root
filesystem.

The specification file includes an args parameter. The args parameter is used
to specify command(s) that get run when the container is started. To change the
command(s) that get executed on start, edit the args parameter of the spec. See
"runc spec --help" for more explanation.`,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "bundle, b",
			Value: "",
			Usage: `path to the root of the bundle directory, defaults to the current directory`,
		},
		cli.StringFlag{
			Name:  "console",
			Value: "",
			Usage: "specify the pty slave path for use with the container",
		},
		cli.BoolFlag{
			Name:  "detach,d",
			Usage: "detach from the container's process",
		},
		cli.StringFlag{
			Name:  "pid-file",
			Value: "",
			Usage: "specify the file to write the process id to",
		},
		cli.BoolFlag{
			Name:  "no-subreaper",
			Usage: "disable the use of the subreaper used to reap reparented processes",
		},
	},
	Action: func(context *cli.Context) {
		bundle := context.String("bundle")
		if bundle != "" {
			if err := os.Chdir(bundle); err != nil {
				fatal(err)
			}
		}
		spec, err := loadSpec(specConfig)
		if err != nil {
			fatal(err)
		}

		notifySocket := os.Getenv("NOTIFY_SOCKET")
		if notifySocket != "" {
			setupSdNotify(spec, notifySocket)
		}

		if os.Geteuid() != 0 {
			fatalf("runc should be run as root")
		}

		status, err := startContainer(context, spec)
		if err != nil {
			fatal(err)
		}
		// exit with the container's exit status so any external supervisor is
		// notified of the exit with the correct exit status.
		os.Exit(status)
	},
}

func init() {
	if len(os.Args) > 1 && os.Args[1] == "init" {
		runtime.GOMAXPROCS(1)
		runtime.LockOSThread()
	}
}

var initCommand = cli.Command{
	Name:  "init",
	Usage: `initialize the namespaces and launch the process (do not call it outside of runc)`,
	Action: func(context *cli.Context) {
		factory, _ := libcontainer.New("")
		if err := factory.StartInitialization(); err != nil {
			// as the error is sent back to the parent there is no need to log
			// or write it to stderr because the parent process will handle this
			os.Exit(1)
		}
		panic("libcontainer: container init failed to exec")
	},
}

func startContainer(context *cli.Context, spec *specs.Spec) (int, error) {
	id := context.Args().First()
	if id == "" {
		return -1, errEmptyID
	}
	container, err := createContainer(context, id, spec)
	if err != nil {
		return -1, err
	}
	detach := context.Bool("detach")
	// Support on-demand socket activation by passing file descriptors into the container init process.
	listenFDs := []*os.File{}
	if os.Getenv("LISTEN_FDS") != "" {
		listenFDs = activation.Files(false)
	}
	r := &runner{
		enableSubreaper: !context.Bool("no-subreaper"),
		shouldDestroy:   true,
		container:       container,
		listenFDs:       listenFDs,
		console:         context.String("console"),
		detach:          detach,
		pidFile:         context.String("pid-file"),
	}
	return r.run(&spec.Process)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"
)

const shutdownGraceTime = 3 * time.Second

var flagPort int
var flagConcurrency string
var flagRestart bool

var cmdStart = &Command{
	Run:   runStart,
	Usage: "start [process name] [-f procfile] [-e env] [-c concurrency] [-p port] [-r]",
	Short: "Start the application",
	Long: `
Start the application specified by a Procfile (defaults to ./Procfile)

Examples:

  forego start
  forego start web
  forego start -f Procfile.test -e .env.test
`,
}

func init() {
	cmdStart.Flag.StringVar(&flagProcfile, "f", "Procfile", "procfile")
	cmdStart.Flag.StringVar(&flagEnv, "e", "", "env")
	cmdStart.Flag.IntVar(&flagPort, "p", 5000, "port")
	cmdStart.Flag.StringVar(&flagConcurrency, "c", "", "concurrency")
	cmdStart.Flag.BoolVar(&flagRestart, "r", false, "restart")
}

func parseConcurrency(value string) (map[string]int, error) {
	concurrency := map[string]int{}
	if strings.TrimSpace(value) == "" {
		return concurrency, nil
	}

	parts := strings.Split(value, ",")
	for _, part := range parts {
		if !strings.Contains(part, "=") {
			return concurrency, errors.New("Parsing concurency")
		}

		nameValue := strings.Split(part, "=")
		n, v := strings.TrimSpace(nameValue[0]), strings.TrimSpace(nameValue[1])
		if n == "" || v == "" {
			return concurrency, errors.New("Parsing concurency")
		}

		numProcs, err := strconv.ParseInt(v, 10, 16)
		if err != nil {
			return concurrency, err
		}

		concurrency[n] = int(numProcs)
	}
	return concurrency, nil
}

type Forego struct {
	outletFactory *OutletFactory

	teardown, teardownNow Barrier // signal shutting down

	wg sync.WaitGroup
}

func (f *Forego) monitorInterrupt() {
	handler := make(chan os.Signal, 1)
	signal.Notify(handler, os.Interrupt)

	first := true

	for sig := range handler {
		switch sig {
		case os.Interrupt:
			fmt.Println("      | ctrl-c detected")

			f.teardown.Fall()
			if !first {
				f.teardownNow.Fall()
			}
			first = false
		}
	}
}

func (f *Forego) startProcess(idx, procNum int, proc ProcfileEntry, env Env, of *OutletFactory) {
	port := flagPort + (idx * 100)

	const interactive = false
	workDir := filepath.Dir(flagProcfile)
	ps := NewProcess(workDir, proc.Command, env, interactive)
	procName := fmt.Sprint(proc.Name, ".", procNum+1)
	ps.Env["PORT"] = strconv.Itoa(port)

	ps.Stdin = nil

	stdout, err := ps.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderr, err := ps.StderrPipe()
	if err != nil {
		panic(err)
	}

	pipeWait := new(sync.WaitGroup)
	pipeWait.Add(2)
	go of.LineReader(pipeWait, procName, idx, stdout, false)
	go of.LineReader(pipeWait, procName, idx, stderr, true)

	of.SystemOutput(fmt.Sprintf("starting %s on port %d", procName, port))

	finished := make(chan struct{}) // closed on process exit

	err = ps.Start()
	if err != nil {
		f.teardown.Fall()
		of.SystemOutput(fmt.Sprint("Failed to start ", procName, ": ", err))
		return
	}

	f.wg.Add(1)
	go func() {
		defer f.wg.Done()
		defer close(finished)
		pipeWait.Wait()
		ps.Wait()
	}()

	f.wg.Add(1)
	go func() {
		defer f.wg.Done()

		// Prevent goroutine from exiting before process has finished.
		defer func() { <-finished }()
		defer f.teardown.Fall()

		select {
		case <-finished:
			if flagRestart {
				f.startProcess(idx, procNum, proc, env, of)
				return
			}

		case <-f.teardown.Barrier():
			// Forego tearing down

			if !osHaveSigTerm {
				of.SystemOutput(fmt.Sprintf("Killing %s", procName))
				ps.Process.Kill()
				return
			}

			of.SystemOutput(fmt.Sprintf("sending SIGTERM to %s", procName))
			ps.SendSigTerm()

			// Give the process a chance to exit, otherwise kill it.
			select {
			case <-f.teardownNow.Barrier():
				of.SystemOutput(fmt.Sprintf("Killing %s", procName))
				ps.SendSigKill()
			case <-finished:
			}
		}
	}()
}

func runStart(cmd *Command, args []string) {
	root := filepath.Dir(flagProcfile)

	if flagEnv == "" {
		flagEnv = filepath.Join(root, ".env")
	}

	pf, err := ReadProcfile(flagProcfile)
	handleError(err)

	env, err := ReadEnv(flagEnv)
	handleError(err)

	concurrency, err := parseConcurrency(flagConcurrency)
	handleError(err)

	of := NewOutletFactory()
	of.Padding = pf.LongestProcessName(concurrency)

	f := &Forego{
		outletFactory: of,
	}

	go f.monitorInterrupt()

	// When teardown fires, start the grace timer
	f.teardown.FallHook = func() {
		go func() {
			time.Sleep(shutdownGraceTime)
			of.SystemOutput("Grace time expired")
			f.teardownNow.Fall()
		}()
	}

	var singleton string = ""
	if len(args) > 0 {
		singleton = args[0]
		if !pf.HasProcess(singleton) {
			of.ErrorOutput(fmt.Sprintf("no such process: %s", singleton))
		}
	}

	for idx, proc := range pf.Entries {
		numProcs := 1
		if value, ok := concurrency[proc.Name]; ok {
			numProcs = value
		}
		for i := 0; i < numProcs; i++ {
			if (singleton == "") || (singleton == proc.Name) {
				f.startProcess(idx, i, proc, env, of)
			}
		}
	}

	<-f.teardown.Barrier()

	f.wg.Wait()
}
<commit_msg>better error message for concurrency<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"
)

const shutdownGraceTime = 3 * time.Second

var flagPort int
var flagConcurrency string
var flagRestart bool

var cmdStart = &Command{
	Run:   runStart,
	Usage: "start [process name] [-f procfile] [-e env] [-c concurrency] [-p port] [-r]",
	Short: "Start the application",
	Long: `
Start the application specified by a Procfile (defaults to ./Procfile)

Examples:

  forego start
  forego start web
  forego start -f Procfile.test -e .env.test
`,
}

func init() {
	cmdStart.Flag.StringVar(&flagProcfile, "f", "Procfile", "procfile")
	cmdStart.Flag.StringVar(&flagEnv, "e", "", "env")
	cmdStart.Flag.IntVar(&flagPort, "p", 5000, "port")
	cmdStart.Flag.StringVar(&flagConcurrency, "c", "", "concurrency")
	cmdStart.Flag.BoolVar(&flagRestart, "r", false, "restart")
}

func parseConcurrency(value string) (map[string]int, error) {
	concurrency := map[string]int{}
	if strings.TrimSpace(value) == "" {
		return concurrency, nil
	}

	parts := strings.Split(value, ",")
	for _, part := range parts {
		if !strings.Contains(part, "=") {
			return concurrency, errors.New("Concurrency should be in the format: foo=1,bar=2")
		}

		nameValue := strings.Split(part, "=")
		n, v := strings.TrimSpace(nameValue[0]), strings.TrimSpace(nameValue[1])
		if n == "" || v == "" {
			return concurrency, errors.New("Concurrency should be in the format: foo=1,bar=2")
		}

		numProcs, err := strconv.ParseInt(v, 10, 16)
		if err != nil {
			return concurrency, err
		}

		concurrency[n] = int(numProcs)
	}
	return concurrency, nil
}

type Forego struct {
	outletFactory *OutletFactory

	teardown, teardownNow Barrier // signal shutting down

	wg sync.WaitGroup
}

func (f *Forego) monitorInterrupt() {
	handler := make(chan os.Signal, 1)
	signal.Notify(handler, os.Interrupt)

	first := true

	for sig := range handler {
		switch sig {
		case os.Interrupt:
			fmt.Println("      | ctrl-c detected")

			f.teardown.Fall()
			if !first {
				f.teardownNow.Fall()
			}
			first = false
		}
	}
}

func (f *Forego) startProcess(idx, procNum int, proc ProcfileEntry, env Env, of *OutletFactory) {
	port := flagPort + (idx * 100)

	const interactive = false
	workDir := filepath.Dir(flagProcfile)
	ps := NewProcess(workDir, proc.Command, env, interactive)
	procName := fmt.Sprint(proc.Name, ".", procNum+1)
	ps.Env["PORT"] = strconv.Itoa(port)

	ps.Stdin = nil

	stdout, err := ps.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderr, err := ps.StderrPipe()
	if err != nil {
		panic(err)
	}

	pipeWait := new(sync.WaitGroup)
	pipeWait.Add(2)
	go of.LineReader(pipeWait, procName, idx, stdout, false)
	go of.LineReader(pipeWait, procName, idx, stderr, true)

	of.SystemOutput(fmt.Sprintf("starting %s on port %d", procName, port))

	finished := make(chan struct{}) // closed on process exit

	err = ps.Start()
	if err != nil {
		f.teardown.Fall()
		of.SystemOutput(fmt.Sprint("Failed to start ", procName, ": ", err))
		return
	}

	f.wg.Add(1)
	go func() {
		defer f.wg.Done()
		defer close(finished)
		pipeWait.Wait()
		ps.Wait()
	}()

	f.wg.Add(1)
	go func() {
		defer f.wg.Done()

		// Prevent goroutine from exiting before process has finished.
		defer func() { <-finished }()
		defer f.teardown.Fall()

		select {
		case <-finished:
			if flagRestart {
				f.startProcess(idx, procNum, proc, env, of)
				return
			}

		case <-f.teardown.Barrier():
			// Forego tearing down

			if !osHaveSigTerm {
				of.SystemOutput(fmt.Sprintf("Killing %s", procName))
				ps.Process.Kill()
				return
			}

			of.SystemOutput(fmt.Sprintf("sending SIGTERM to %s", procName))
			ps.SendSigTerm()

			// Give the process a chance to exit, otherwise kill it.
			select {
			case <-f.teardownNow.Barrier():
				of.SystemOutput(fmt.Sprintf("Killing %s", procName))
				ps.SendSigKill()
			case <-finished:
			}
		}
	}()
}

func runStart(cmd *Command, args []string) {
	root := filepath.Dir(flagProcfile)

	if flagEnv == "" {
		flagEnv = filepath.Join(root, ".env")
	}

	pf, err := ReadProcfile(flagProcfile)
	handleError(err)

	env, err := ReadEnv(flagEnv)
	handleError(err)

	concurrency, err := parseConcurrency(flagConcurrency)
	handleError(err)

	of := NewOutletFactory()
	of.Padding = pf.LongestProcessName(concurrency)

	f := &Forego{
		outletFactory: of,
	}

	go f.monitorInterrupt()

	// When teardown fires, start the grace timer
	f.teardown.FallHook = func() {
		go func() {
			time.Sleep(shutdownGraceTime)
			of.SystemOutput("Grace time expired")
			f.teardownNow.Fall()
		}()
	}

	var singleton string = ""
	if len(args) > 0 {
		singleton = args[0]
		if !pf.HasProcess(singleton) {
			of.ErrorOutput(fmt.Sprintf("no such process: %s", singleton))
		}
	}

	for idx, proc := range pf.Entries {
		numProcs := 1
		if value, ok := concurrency[proc.Name]; ok {
			numProcs = value
		}
		for i := 0; i < numProcs; i++ {
			if (singleton == "") || (singleton == proc.Name) {
				f.startProcess(idx, i, proc, env, of)
			}
		}
	}

	<-f.teardown.Barrier()

	f.wg.Wait()
}
<|endoftext|>


<commit_before>package transaction

import (
	"errors"
	"time"

	"github.com/stefankopieczek/gossip/base"
	"github.com/stefankopieczek/gossip/log"
	"github.com/stefankopieczek/gossip/transport"
)

var (
	global *Manager = &Manager{
		txs: map[key]Transaction{},
	}
)

type Manager struct {
	txs       map[key]Transaction
	transport *transport.Manager
}

// Transactions are identified by the branch parameter in the top Via header, and the method. (RFC 3261 17.1.3)
type key struct {
	branch string
	method string
}

func NewManager(trans, addr string) (*Manager, error) {
	t, err := transport.NewManager(trans, addr)
	if err != nil {
		return nil, err
	}

	mng := &Manager{
		txs:       map[key]Transaction{},
		transport: t,
	}

	// Spin up a goroutine to pull messages up from the depths.
	go func() {
		c := mng.transport.GetChannel()
		for msg := range c {
			mng.Handle(msg)
		}
	}()

	return mng, nil
}

func (mng *Manager) putTx(tx Transaction) {
	viaHeaders := tx.Origin().Headers("Via")
	if len(viaHeaders) == 0 {
		log.Warn("No Via header on new transaction. Transaction will be dropped.")
		return
	}

	via, ok := viaHeaders[0].(base.ViaHeader)
	if !ok {
		panic(errors.New("Headers('Via') returned non-Via header!"))
	}

	branch, ok := via[0].Params["branch"]
	if !ok {
		log.Warn("No branch parameter on top Via header.  Transactino will be dropped.")
	}

	// TODO: Safety

	key := key{*branch, string(tx.Origin().Method)}
	mng.txs[key] = tx
}

func (mng *Manager) getTx(s base.SipMessage) (Transaction, bool) {
	viaHeaders := s.Headers("Via")
	via, ok := viaHeaders[0].(base.ViaHeader)
	if !ok {
		panic(errors.New("Headers('Via') returned non-Via header!"))
	}

	branch, ok := via[0].Params["branch"]
	if !ok {
		log.Warn("No branch parameter on top Via header.  Transactino will be dropped.")
	}

	var method string
	switch s := s.(type) {
	case *base.Request:
		method = string(s.Method)
	case *base.Response:
		cseq, _ := s.Headers("CSeq")[0].(*base.CSeq)
		method = string(cseq.MethodName)
	}

	key := key{*branch, method}
	tx, ok := mng.txs[key]

	return tx, ok
}

func (mng *Manager) Handle(msg base.SipMessage) {
	switch m := msg.(type) {
	case *base.Request:
		// TODO: Create a new server transaction.
	case *base.Response:
		mng.Correlate(m)
	default:
		// TODO: Error
	}
}

// Create Client transaction.
func (mng *Manager) Send(r *base.Request, dest string) (<-chan *base.Response, error) {
	log.Debug("Sending to %v: %v", dest, r.String())

	tx := &ClientTransaction{}
	tx.origin = r
	tx.dest = dest

	tx.initFSM()

	respChan := make(chan *base.Response, 3)
	tx.tu = (chan<- *base.Response)(respChan)
	tx.tu_err = make(chan error, 1)

	tx.timer_a_time = T1
	tx.timer_a = time.NewTimer(tx.timer_a_time)
	tx.timer_b = time.NewTimer(64 * T1)

	err := mng.transport.Send(dest, r)
	if err != nil {
		tx.fsm.Spin(client_input_transport_err)
	}

	mng.putTx(tx)

	return (<-chan *base.Response)(respChan), err
}

// Give a received response to the correct transaction.
func (mng *Manager) Correlate(r *base.Response) {
	tx, ok := mng.getTx(r)
	if !ok {
		// TODO: Something
	}

	tx.Receive(r)
}
<commit_msg>Transaction layer calls on transport layer to listen.<commit_after>package transaction

import (
	"errors"
	"time"

	"github.com/stefankopieczek/gossip/base"
	"github.com/stefankopieczek/gossip/log"
	"github.com/stefankopieczek/gossip/transport"
)

var (
	global *Manager = &Manager{
		txs: map[key]Transaction{},
	}
)

type Manager struct {
	txs       map[key]Transaction
	transport *transport.Manager
}

// Transactions are identified by the branch parameter in the top Via header, and the method. (RFC 3261 17.1.3)
type key struct {
	branch string
	method string
}

func NewManager(trans, addr string) (*Manager, error) {
	t, err := transport.NewManager(trans, addr)
	if err != nil {
		return nil, err
	}

	mng := &Manager{
		txs:       map[key]Transaction{},
		transport: t,
	}

	// Spin up a goroutine to pull messages up from the depths.
	go func() {
		c := mng.transport.GetChannel()
		for msg := range c {
			mng.Handle(msg)
		}
	}()

	mng.transport.Listen()

	return mng, nil
}

func (mng *Manager) putTx(tx Transaction) {
	viaHeaders := tx.Origin().Headers("Via")
	if len(viaHeaders) == 0 {
		log.Warn("No Via header on new transaction. Transaction will be dropped.")
		return
	}

	via, ok := viaHeaders[0].(base.ViaHeader)
	if !ok {
		panic(errors.New("Headers('Via') returned non-Via header!"))
	}

	branch, ok := via[0].Params["branch"]
	if !ok {
		log.Warn("No branch parameter on top Via header.  Transactino will be dropped.")
	}

	// TODO: Safety

	key := key{*branch, string(tx.Origin().Method)}
	mng.txs[key] = tx
}

func (mng *Manager) getTx(s base.SipMessage) (Transaction, bool) {
	viaHeaders := s.Headers("Via")
	via, ok := viaHeaders[0].(base.ViaHeader)
	if !ok {
		panic(errors.New("Headers('Via') returned non-Via header!"))
	}

	branch, ok := via[0].Params["branch"]
	if !ok {
		log.Warn("No branch parameter on top Via header.  Transactino will be dropped.")
	}

	var method string
	switch s := s.(type) {
	case *base.Request:
		method = string(s.Method)
	case *base.Response:
		cseq, _ := s.Headers("CSeq")[0].(*base.CSeq)
		method = string(cseq.MethodName)
	}

	key := key{*branch, method}
	tx, ok := mng.txs[key]

	return tx, ok
}

func (mng *Manager) Handle(msg base.SipMessage) {
	log.Info("Received message: %s", msg.Short())
	switch m := msg.(type) {
	case *base.Request:
		// TODO: Create a new server transaction.
	case *base.Response:
		mng.Correlate(m)
	default:
		// TODO: Error
	}
}

// Create Client transaction.
func (mng *Manager) Send(r *base.Request, dest string) (<-chan *base.Response, error) {
	log.Debug("Sending to %v: %v", dest, r.String())

	tx := &ClientTransaction{}
	tx.origin = r
	tx.dest = dest

	tx.initFSM()

	respChan := make(chan *base.Response, 3)
	tx.tu = (chan<- *base.Response)(respChan)
	tx.tu_err = make(chan error, 1)

	tx.timer_a_time = T1
	tx.timer_a = time.NewTimer(tx.timer_a_time)
	tx.timer_b = time.NewTimer(64 * T1)

	err := mng.transport.Send(dest, r)
	if err != nil {
		tx.fsm.Spin(client_input_transport_err)
	}

	mng.putTx(tx)

	return (<-chan *base.Response)(respChan), err
}

// Give a received response to the correct transaction.
func (mng *Manager) Correlate(r *base.Response) {
	tx, ok := mng.getTx(r)
	if !ok {
		// TODO: Something
	}

	tx.Receive(r)
}
<|endoftext|>


<commit_before>package transform

import (
	"github.com/teomat/mater/vect"
	"math"
)

type Rotation struct {
	//sine and cosine.
	S, C float64
}

func (rot *Rotation) SetIdentity() {
	rot.S = 0
	rot.C = 1
}

func (rot *Rotation) SetAngle(angle float64) {
	rot.C = math.Cos(angle)
	rot.S = math.Sin(angle)
}

func (rot *Rotation) Angle() float64 {
	return math.Atan2(rot.S, rot.C)
}

//rotates the input vector.
func (rot *Rotation) RotateVect(v vect.Vect) vect.Vect {
	return vect.Vect{
		X: v.X*rot.C - v.Y*rot.S,
		Y: v.X*rot.S + v.Y*rot.C,
	}
}

type Transform struct {
	Position vect.Vect
	Rotation
}

func (xf *Transform) SetIdentity() {
	xf.Position = vect.Vect{}
	xf.Rotation.SetIdentity()
}

func (xf *Transform) Set(pos vect.Vect, rot float64) {
	xf.Position = pos
	xf.SetAngle(rot)
}

//moves and roates the input vector.
func (xf *Transform) TransformVect(v vect.Vect) vect.Vect {
	return vect.Add(xf.Position, xf.RotateVect(v))
}
<commit_msg>added constructors to package transform<commit_after>package transform

import (
	"github.com/teomat/mater/vect"
	"math"
)

type Rotation struct {
	//sine and cosine.
	S, C float64
}

func NewRotation(angle float64) Rotation {
	return Rotation{
		C: math.Cos(angle),
		S: math.Sin(angle),
	}
}

func (rot *Rotation) SetIdentity() {
	rot.S = 0
	rot.C = 1
}

func (rot *Rotation) SetAngle(angle float64) {
	rot.C = math.Cos(angle)
	rot.S = math.Sin(angle)
}

func (rot *Rotation) Angle() float64 {
	return math.Atan2(rot.S, rot.C)
}

//rotates the input vector.
func (rot *Rotation) RotateVect(v vect.Vect) vect.Vect {
	return vect.Vect{
		X: v.X*rot.C - v.Y*rot.S,
		Y: v.X*rot.S + v.Y*rot.C,
	}
}

type Transform struct {
	Position vect.Vect
	Rotation
}

func NewTransform(pos vect.Vect, angle float64) Transform {
	return Transform{
		Position: pos,
		Rotation: NewRotation(angle),
	}
}

func (xf *Transform) SetIdentity() {
	xf.Position = vect.Vect{}
	xf.Rotation.SetIdentity()
}

func (xf *Transform) Set(pos vect.Vect, rot float64) {
	xf.Position = pos
	xf.SetAngle(rot)
}

//moves and roates the input vector.
func (xf *Transform) TransformVect(v vect.Vect) vect.Vect {
	return vect.Add(xf.Position, xf.RotateVect(v))
}
<|endoftext|>


<commit_before>package translate

import (
	"net/http"
	"net/rpc"
	"strings"
	"unicode"

	"gitgud.io/softashell/rpgmaker-patch-translator/text"
	"github.com/Jeffail/tunny"
	log "github.com/sirupsen/logrus"
)

type translateRequest struct {
	Text string `json:"text"`
	From string `json:"from"`
	To   string `json:"to"`
}

type translateResponse struct {
	Text            string `json:"text"`
	From            string `json:"from"`
	To              string `json:"to"`
	TranslationText string `json:"translationText"`
}

var httpTransport *http.Transport
var pool *tunny.Pool

func Init() {
	httpTransport = &http.Transport{}

	workerCount := 256

	pool = tunny.New(workerCount, func() tunny.Worker {
		return newComfyWorker()
	})
}

func comfyTranslate(client *rpc.Client, req translateRequest) translateResponse {
	var reply translateResponse

	err := client.Call("Comfy.Translate", req, &reply)
	if err != nil {
		log.Fatal("translation service error:", err)
	}

	return reply
}

func String(str string) (string, error) {
	if !text.ShouldTranslate(str) {
		return str, nil
	}

	if str == "っ" {
		return "", nil
	}

	request := translateRequest{
		From: "ja",
		To:   "en",
		Text: str,
	}

	response := pool.Process(request).(translateResponse)

	out := response.TranslationText

	if len(out) < 1 {
		log.Warnf("Translator returned empty string, replacing with original text %q", str)
		out = str
	} else {
		out = cleanTranslation(out)
	}

	return out, nil
}

func cleanTranslation(str string) string {
	// Removes any rune that isn't printable or a space
	isValid := func(r rune) rune {
		if !unicode.IsPrint(r) && !unicode.IsSpace(r) {
			return -1
		}

		return r
	}

	str = strings.Map(isValid, str)

	str = strings.Replace(str, "\\u0026", "＆", -1)
	str = strings.Replace(str, "\\u003c", "<", -1)
	str = strings.Replace(str, "\\u003e", ">", -1)

	if strings.Contains(str, "\\u0") {
		log.Warnf("Found unexpected escaped character in translation %s", str)
	}

	str = strings.Replace(str, "\\", "", -1)

	// Repeated whitespace
	str = text.ReplaceRegex(str, `\s{2,}`, " ")

	// ー ー ー ー
	str = text.ReplaceRegex(str, `\s+((\s+)?[-―ー]){2,}`, " ー")

	// · · · ·
	str = text.ReplaceRegex(str, `(\s+)?((\s+)?[·]+){3,}`, " ···")

	str = text.ReplaceRegex(str, `((\s+)?っ)+`, "")

	return str
}
<commit_msg>Spam more threads<commit_after>package translate

import (
	"net/http"
	"net/rpc"
	"runtime"
	"strings"
	"unicode"

	"gitgud.io/softashell/rpgmaker-patch-translator/text"
	"github.com/Jeffail/tunny"
	log "github.com/sirupsen/logrus"
)

type translateRequest struct {
	Text string `json:"text"`
	From string `json:"from"`
	To   string `json:"to"`
}

type translateResponse struct {
	Text            string `json:"text"`
	From            string `json:"from"`
	To              string `json:"to"`
	TranslationText string `json:"translationText"`
}

var httpTransport *http.Transport
var pool *tunny.Pool

func Init() {
	httpTransport = &http.Transport{}

	workerCount := 128 * runtime.NumCPU()

	pool = tunny.New(workerCount, func() tunny.Worker {
		return newComfyWorker()
	})
}

func comfyTranslate(client *rpc.Client, req translateRequest) translateResponse {
	var reply translateResponse

	err := client.Call("Comfy.Translate", req, &reply)
	if err != nil {
		log.Fatal("translation service error:", err)
	}

	return reply
}

func String(str string) (string, error) {
	if !text.ShouldTranslate(str) {
		return str, nil
	}

	if str == "っ" {
		return "", nil
	}

	request := translateRequest{
		From: "ja",
		To:   "en",
		Text: str,
	}

	response := pool.Process(request).(translateResponse)

	out := response.TranslationText

	if len(out) < 1 {
		log.Warnf("Translator returned empty string, replacing with original text %q", str)
		out = str
	} else {
		out = cleanTranslation(out)
	}

	return out, nil
}

func cleanTranslation(str string) string {
	// Removes any rune that isn't printable or a space
	isValid := func(r rune) rune {
		if !unicode.IsPrint(r) && !unicode.IsSpace(r) {
			return -1
		}

		return r
	}

	str = strings.Map(isValid, str)

	str = strings.Replace(str, "\\u0026", "＆", -1)
	str = strings.Replace(str, "\\u003c", "<", -1)
	str = strings.Replace(str, "\\u003e", ">", -1)

	if strings.Contains(str, "\\u0") {
		log.Warnf("Found unexpected escaped character in translation %s", str)
	}

	str = strings.Replace(str, "\\", "", -1)

	// Repeated whitespace
	str = text.ReplaceRegex(str, `\s{2,}`, " ")

	// ー ー ー ー
	str = text.ReplaceRegex(str, `\s+((\s+)?[-―ー]){2,}`, " ー")

	// · · · ·
	str = text.ReplaceRegex(str, `(\s+)?((\s+)?[·]+){3,}`, " ···")

	str = text.ReplaceRegex(str, `((\s+)?っ)+`, "")

	return str
}
<|endoftext|>


<commit_before>// +build !appengine

package bugsnag

import (
	"github.com/bitly/go-simplejson"
	"github.com/bugsnag/osext"
	"os"
	"os/exec"
	"testing"
	"time"
)

func TestPanicHandler(t *testing.T) {
	startTestServer()

	exePath, err := osext.Executable()
	if err != nil {
		t.Fatal(err)
	}

	// Use the same trick as panicwrap() to re-run ourselves.
	// In the init() block below, we will then panic.
	cmd := exec.Command(exePath, os.Args[1:]...)
	cmd.Env = append(os.Environ(), "BUGSNAG_API_KEY="+testAPIKey, "BUGSNAG_ENDPOINT="+testEndpoint, "please_panic=please_panic")

	if err = cmd.Start(); err != nil {
		t.Fatal(err)
	}

	if err = cmd.Wait(); err.Error() != "exit status 2" {
		t.Fatal(err)
	}

	json, err := simplejson.NewJson(<-postedJSON)
	if err != nil {
		t.Fatal(err)
	}

	event := json.Get("events").GetIndex(0)

	if event.Get("severity").MustString() != "error" {
		t.Errorf("severity should be error")
	}
	exception := event.Get("exceptions").GetIndex(0)

	if exception.Get("message").MustString() != "ruh roh" {
		t.Errorf("caught wrong panic")
	}

	if exception.Get("errorClass").MustString() != "panic" {
		t.Errorf("caught wrong panic")
	}

	frame := exception.Get("stacktrace").GetIndex(1)

	// Yeah, we just caught a panic from the init() function below and sent it to the server running above (mindblown)
	if frame.Get("inProject").MustBool() != true ||
		frame.Get("file").MustString() != "panicwrap_test.go" ||
		frame.Get("lineNumber").MustInt() == 0 {
		t.Errorf("stack trace seemed wrong: %v", frame)
	}
}

func init() {
	if os.Getenv("please_panic") != "" {
		Configure(Configuration{APIKey: os.Getenv("BUGSNAG_API_KEY"), Endpoint: os.Getenv("BUGSNAG_ENDPOINT"), ProjectPackages: []string{"github.com/bugsnag/bugsnag-go"}})
		go func() {
			panick()
		}()
		// Plenty of time to crash, it shouldn't need any of it.
		time.Sleep(1 * time.Second)
	}
}

func panick() {
	panic("ruh roh")
}
<commit_msg>This test is insane, maybe in the *mindblown* way<commit_after>// +build !appengine

package bugsnag

import (
	"github.com/bitly/go-simplejson"
	"github.com/bugsnag/osext"
	"os"
	"os/exec"
	"testing"
	"time"
)

func TestPanicHandler(t *testing.T) {
	startTestServer()

	exePath, err := osext.Executable()
	if err != nil {
		t.Fatal(err)
	}

	// Use the same trick as panicwrap() to re-run ourselves.
	// In the init() block below, we will then panic.
	cmd := exec.Command(exePath, os.Args[1:]...)
	cmd.Env = append(os.Environ(), "BUGSNAG_API_KEY="+testAPIKey, "BUGSNAG_ENDPOINT="+testEndpoint, "please_panic=please_panic")

	if err = cmd.Start(); err != nil {
		t.Fatal(err)
	}

	if err = cmd.Wait(); err.Error() != "exit status 2" {
		t.Fatal(err)
	}

	json, err := simplejson.NewJson(<-postedJSON)
	if err != nil {
		t.Fatal(err)
	}

	event := json.Get("events").GetIndex(0)

	if event.Get("severity").MustString() != "error" {
		t.Errorf("severity should be error")
	}
	exception := event.Get("exceptions").GetIndex(0)

	message := exception.Get("message").MustString()
	if message != "ruh roh" {
		t.Errorf("caught wrong panic message: '%s'", message)
	}

	errorClass := exception.Get("errorClass").MustString()
	if errorClass != "*errors.errorString" {
		t.Errorf("caught wrong panic errorClass: '%s'", errorClass)
	}

	stacktrace := exception.Get("stacktrace")

	// Yeah, we just caught a panic from the init() function below and sent it to the server running above (mindblown)
	frame := stacktrace.GetIndex(1)
	if frame.Get("inProject").MustBool() != true ||
		frame.Get("file").MustString() != "panicwrap_test.go" ||
		frame.Get("lineNumber").MustInt() == 0 {
		t.Errorf("stack frame seems wrong at index 1: %v", frame)
	}
}

func init() {
	if os.Getenv("please_panic") != "" {
		Configure(Configuration{APIKey: os.Getenv("BUGSNAG_API_KEY"), Endpoint: os.Getenv("BUGSNAG_ENDPOINT"), ProjectPackages: []string{"github.com/bugsnag/bugsnag-go"}})
		go func() {
			defer AutoNotify()

			panick()
		}()
		// Plenty of time to crash, it shouldn't need any of it.
		time.Sleep(1 * time.Second)
	}
}

func panick() {
	panic("ruh roh")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	kingpin "gopkg.in/alecthomas/kingpin.v2"

	"github.com/boltdb/bolt"
	homedir "github.com/mitchellh/go-homedir"
)

var (
	alias            string
	aliasDescription string
)

func init() {
	action.Arg("name", "name for the alias action").
		Required().
		StringVar(&alias)

	action.Arg("method", "the method to use for the action").
		Required().
		StringVar(&request.Method)

	action.Arg("path", "the path to perform the action on").
		Required().
		StringVar(&request.Path)

	action.Arg("description", "a short description of the alias, will be used in generated help documentation").
		StringVar(&aliasDescription)

	dir, err := homedir.Dir()
	if err != nil {
		panic(err)
	}
	dbFile = fmt.Sprintf("%s/%s", dir, ".rest.db")

	// parse aliases and make them part of the command, aliases will show up on help,
	// aliases can be called directly as a subcommand of 'rest'
	if err := setAliases(); err != nil {
		panic(err)
	}

}

func setAliases() error {
	var err error
	db, err = bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	return db.View(func(tx *bolt.Tx) error {
		// if the services haven't been initialised there will be nothing here, so all
		// aliases should be ignored and failure to find a particular bucket is safe.
		info := tx.Bucket([]byte("info"))
		if info == nil {
			return nil
		}

		current := info.Get([]byte("current"))
		if current == nil {
			return nil
		}

		services := tx.Bucket([]byte("services"))
		if services == nil {
			return nil
		}

		sb := services.Bucket(current)
		if sb == nil {
			return nil
		}

		aliases := sb.Bucket([]byte("aliases"))
		if aliases == nil {
			return nil
		}

		return aliases.ForEach(func(k, _ []byte) error {
			b := aliases.Bucket(k)
			a := kingpin.Command(string(k), string(b.Get([]byte("description"))))
			a.Arg("data", "data to send in the request").
				StringVar(&request.Data)
			requestFlags(a)

			return nil
		})
	})
}

func addAlias() error {
	return db.Update(func(tx *bolt.Tx) error {
		sb, err := request.ServiceBucket(tx)
		if err != nil {
			return err
		}

		ab, err := sb.CreateBucketIfNotExists([]byte("aliases"))
		if err != nil {
			return err
		}

		a, err := ab.CreateBucketIfNotExists([]byte(alias))
		if err != nil {
			return err
		}

		if err := a.Put([]byte("method"), []byte(request.Method)); err != nil {
			return err
		}

		if err := a.Put([]byte("path"), []byte(request.Path)); err != nil {
			return err
		}

		if aliasDescription != "" {
			if err := a.Put([]byte("description"), []byte(aliasDescription)); err != nil {
				return err
			}

		}

		return nil
	})
}

func Perform(name string) {
	err := db.View(func(tx *bolt.Tx) error {
		sb, err := request.ServiceBucket(tx)
		if err != nil {
			return err
		}

		b := sb.Bucket([]byte("aliases"))
		if b == nil {
			return ErrNoAliases
		}

		a := b.Bucket([]byte(name))
		if a == nil {
			return ErrNoAlias{Alias: name}
		}

		method := string(a.Get([]byte("method")))
		path := string(a.Get([]byte("path")))

		request.Method = method
		request.Path = path

		return nil
	})

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	Do(request.Method)
}
<commit_msg>Only add data argument for post, and put aliases<commit_after>package main

import (
	"fmt"
	"os"

	kingpin "gopkg.in/alecthomas/kingpin.v2"

	"github.com/boltdb/bolt"
	homedir "github.com/mitchellh/go-homedir"
)

var (
	alias            string
	aliasDescription string
)

func init() {
	action.Arg("name", "name for the alias action").
		Required().
		StringVar(&alias)

	action.Arg("method", "the method to use for the action").
		Required().
		StringVar(&request.Method)

	action.Arg("path", "the path to perform the action on").
		Required().
		StringVar(&request.Path)

	action.Arg("description", "a short description of the alias, will be used in generated help documentation").
		StringVar(&aliasDescription)

	dir, err := homedir.Dir()
	if err != nil {
		panic(err)
	}
	dbFile = fmt.Sprintf("%s/%s", dir, ".rest.db")

	// parse aliases and make them part of the command, aliases will show up on help,
	// aliases can be called directly as a subcommand of 'rest'
	if err := setAliases(); err != nil {
		panic(err)
	}

}

func setAliases() error {
	var err error
	db, err = bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	return db.View(func(tx *bolt.Tx) error {
		// if the services haven't been initialised there will be nothing here, so all
		// aliases should be ignored and failure to find a particular bucket is safe.
		info := tx.Bucket([]byte("info"))
		if info == nil {
			return nil
		}

		current := info.Get([]byte("current"))
		if current == nil {
			return nil
		}

		services := tx.Bucket([]byte("services"))
		if services == nil {
			return nil
		}

		sb := services.Bucket(current)
		if sb == nil {
			return nil
		}

		aliases := sb.Bucket([]byte("aliases"))
		if aliases == nil {
			return nil
		}

		return aliases.ForEach(func(k, _ []byte) error {
			b := aliases.Bucket(k)
			a := kingpin.Command(string(k), string(b.Get([]byte("description"))))

			// attached data arguments to post and put methods
			method := string(b.Get([]byte("method")))
			if method == "post" || method == "put" {
				a.Arg("data", "data to send in the request").
					StringVar(&request.Data)
			}

			requestFlags(a)

			return nil
		})
	})
}

func addAlias() error {
	return db.Update(func(tx *bolt.Tx) error {
		sb, err := request.ServiceBucket(tx)
		if err != nil {
			return err
		}

		ab, err := sb.CreateBucketIfNotExists([]byte("aliases"))
		if err != nil {
			return err
		}

		a, err := ab.CreateBucketIfNotExists([]byte(alias))
		if err != nil {
			return err
		}

		if err := a.Put([]byte("method"), []byte(request.Method)); err != nil {
			return err
		}

		if err := a.Put([]byte("path"), []byte(request.Path)); err != nil {
			return err
		}

		if aliasDescription != "" {
			if err := a.Put([]byte("description"), []byte(aliasDescription)); err != nil {
				return err
			}

		}

		return nil
	})
}

func Perform(name string) {
	err := db.View(func(tx *bolt.Tx) error {
		sb, err := request.ServiceBucket(tx)
		if err != nil {
			return err
		}

		b := sb.Bucket([]byte("aliases"))
		if b == nil {
			return ErrNoAliases
		}

		a := b.Bucket([]byte(name))
		if a == nil {
			return ErrNoAlias{Alias: name}
		}

		method := string(a.Get([]byte("method")))
		path := string(a.Get([]byte("path")))

		request.Method = method
		request.Path = path

		return nil
	})

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	Do(request.Method)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"log"
	"net"
)

type SBState struct {
	con			net.Conn
	chQuit		chan bool
}

func InitState(con net.Conn) *SBState {
	s := SBState{con: con}
	return &s
}

func (s *SBState) HandleReply(reply []byte) bool {
	var m Reply
	err := json.Unmarshal(reply, &m)
	deny(err)
	log.Println(m)
	// log.Println(string(reply))

	return true
}<commit_msg>HandleReply updated<commit_after>package main

import (
	"encoding/json"
	"log"
	"net"
)

type SBState struct {
	con			net.Conn
	chQuit		chan bool
}

func InitState(con net.Conn) *SBState {
	s := SBState{con: con}
	s.chQuit = make(chan bool, 5)
	return &s
}

func (s *SBState) HandleReply(reply []byte) bool {
	if len(reply) < 2 {
		log.Println("HandleReply: Reply too short")
		return false
	}

	var m Reply
	err := json.Unmarshal(reply, &m)
	deny(err)
	log.Println(m)
	// log.Println(string(reply))

	return true
}<|endoftext|>


<commit_before>// Copyright (c) Liam Stanley <me@liamstanley.io>. All rights reserved. Use
// of this source code is governed by the MIT license that can be found in
// the LICENSE file.

package girc

import (
	"fmt"
	"net"
	"strings"
	"sync"
	"time"
)

// state represents the actively-changing variables within the client
// runtime.
type state struct {
	// m is a RW mutex lock, used to guard the state from goroutines causing
	// corruption.
	mu sync.RWMutex

	// reader is the socket buffer reader from the IRC server.
	reader *ircDecoder
	// reader is the socket buffer write to the IRC server.
	writer *ircEncoder
	// conn is a net.Conn reference to the IRC server.
	conn net.Conn

	// connected is true if we're actively connected to a server.
	connected bool
	// connTime is the time at which the client has connected to a server.
	connTime *time.Time
	// quitting is used to determine if we've finished quitting/cleaning up.
	quitting bool
	// reconnecting lets the internal state know a reconnect is occurring.
	reconnecting bool
	// nick is the tracker for our nickname on the server.
	nick string
	// channels represents all channels we're active in.
	channels map[string]*Channel
	// enabledCap are the capabilities which are enabled for this connection.
	enabledCap []string
	// tmpCap are the capabilties which we share with the server during the
	// last capability check. These will get sent once we have received the
	// last capability list command from the server.
	tmpCap []string
	// serverOptions are the standard capabilities and configurations
	// supported by the server at connection time. This also includes
	// RPL_ISUPPORT entries.
	serverOptions map[string]string
	// motd is the servers message of the day.
	motd string
}

// User represents an IRC user and the state attached to them.
type User struct {
	// Nick is the users current nickname.
	Nick string
	// Ident is the users username/ident. Ident is commonly prefixed with a
	// "~", which indicates that they do not have a identd server setup for
	// authentication.
	Ident string
	// Host is the visible host of the users connection that the server has
	// provided to us for their connection. May not always be accurate due to
	// many networks spoofing/hiding parts of the hostname for privacy
	// reasons.
	Host string

	// FirstSeen represents the first time that the user was seen by the
	// client for the given channel. Only usable if from state, not in past.
	FirstSeen time.Time
	// LastActive represents the last time that we saw the user active,
	// which could be during nickname change, message, channel join, etc.
	// Only usable if from state, not in past.
	LastActive time.Time

	// Perms are the user permissions applied to this user that affect the given
	// channel. This supports non-rfc style modes like Admin, Owner, and HalfOp.
	// If you want to easily check if a user has permissions equal or greater
	// than OP, use Perms.IsAdmin().
	Perms UserPerms

	// Extras are things added on by additional tracking methods, which may
	// or may not work on the IRC server in mention.
	Extras struct {
		// Name is the users "realname" or full name. Commonly contains links
		// to the IRC client being used, or something of non-importance. May
		// also be empty if unsupported by the server/tracking is disabled.
		Name string
		// Account refers to the account which the user is authenticated as.
		// This differs between each network (e.g. usually Nickserv, but
		// could also be something like Undernet). May also be empty if
		// unsupported by the server/tracking is disabled.
		Account string
		// Away refers to the away status of the user. An empty string
		// indicates that they are active, otherwise the string is what they
		// set as their away message. May also be empty if unsupported by the
		// server/tracking is disabled.
		Away string
	}
}

// Message returns an event which can be used to send a response to the user
// as a private message.
func (u *User) Message(message string) *Event {
	return &Event{Command: PRIVMSG, Params: []string{u.Nick}, Trailing: message}
}

// Messagef returns an event which can be used to send a response to the user
// as a private message. format is a printf format string, which a's
// arbitrary arguments will be passed to.
func (u *User) Messagef(format string, a ...interface{}) *Event {
	return u.Message(fmt.Sprintf(format, a...))
}

// MessageTo returns an event which can be used to send a response to the
// user in a channel as a private message.
func (u *User) MessageTo(channel, message string) *Event {
	return &Event{Command: PRIVMSG, Params: []string{u.Nick}, Trailing: channel + ": " + message}
}

// MessageTof returns an event which can be used to send a response to the
// channel. format is a printf format string, which a's arbitrary arguments
// will be passed to.
func (u *User) MessageTof(channel, format string, a ...interface{}) *Event {
	return u.MessageTo(channel, fmt.Sprintf(format, a...))
}

// Lifetime represents the amount of time that has passed since we have first
// seen the user.
func (u *User) Lifetime() time.Duration {
	return time.Since(u.FirstSeen)
}

// Active represents the the amount of time that has passed since we have
// last seen the user.
func (u *User) Active() time.Duration {
	return time.Since(u.LastActive)
}

// IsActive returns true if they were active within the last 30 minutes.
func (u *User) IsActive() bool {
	return u.Active() < (time.Minute * 30)
}

// Channel represents an IRC channel and the state attached to it.
type Channel struct {
	// Name of the channel. Must be rfc compliant. Always represented as
	// lower-case, to ensure that the channel is only being tracked once.
	Name string
	// Topic of the channel.
	Topic string
	// users represents the users that we can currently see within the
	// channel.
	users map[string]*User
	// Joined represents the first time that the client joined the channel.
	Joined time.Time
	// Modes are the known channel modes that the bot has captured.
	Modes CModes
}

// Message returns an event which can be used to send a response to the channel.
func (c *Channel) Message(message string) *Event {
	return &Event{Command: PRIVMSG, Params: []string{c.Name}, Trailing: message}
}

// Messagef returns an event which can be used to send a response to the
// channel. format is a printf format string, which a's arbitrary arguments
// will be passed to.
func (c *Channel) Messagef(format string, a ...interface{}) *Event {
	return c.Message(fmt.Sprintf(format, a...))
}

// Lifetime represents the amount of time that has passed since we have first
// joined the channel.
func (c *Channel) Lifetime() time.Duration {
	return time.Since(c.Joined)
}

// newState returns a clean client state.
func newState() *state {
	s := &state{}

	s.channels = make(map[string]*Channel)
	s.serverOptions = make(map[string]string)
	s.connected = false

	return s
}

// createChanIfNotExists creates the channel in state, if not already done.
// Always use state.mu for transaction.
func (s *state) createChanIfNotExists(name string) (channel *Channel) {
	// Not a valid channel.
	if !IsValidChannel(name) {
		return nil
	}

	supported := s.chanModes()
	prefixes, _ := parsePrefixes(s.userPrefixes())

	name = strings.ToLower(name)
	if _, ok := s.channels[name]; !ok {
		channel = &Channel{
			Name:   name,
			users:  make(map[string]*User),
			Joined: time.Now(),
			Modes:  newCModes(supported, prefixes),
		}
		s.channels[name] = channel
	} else {
		channel = s.channels[name]
	}

	return channel
}

// deleteChannel removes the channel from state, if not already done. Always
// use state.mu for transaction.
func (s *state) deleteChannel(name string) {
	channel := s.createChanIfNotExists(name)
	if channel == nil {
		return
	}

	if _, ok := s.channels[channel.Name]; ok {
		delete(s.channels, channel.Name)
	}
}

// lookupChannel returns a reference to a channel with a given case-insensitive
// name. nil returned if no results found.
func (s *state) lookupChannel(name string) *Channel {
	if !IsValidChannel(name) {
		return nil
	}

	return s.channels[strings.ToLower(name)]
}

// createUserIfNotExists creates the channel and user in state, if not already
// done. Always use state.mu for transaction.
func (s *state) createUserIfNotExists(channelName, nick string) (user *User) {
	if !IsValidNick(nick) {
		return nil
	}

	channel := s.createChanIfNotExists(channelName)
	if channel == nil {
		return nil
	}

	if _, ok := channel.users[nick]; ok {
		channel.users[nick].LastActive = time.Now()
		return channel.users[nick]
	}

	user = &User{Nick: nick, FirstSeen: time.Now(), LastActive: time.Now()}
	channel.users[nick] = user

	return user
}

// deleteUser removes the user from channel state. Always use state.mu for
// transaction.
func (s *state) deleteUser(nick string) {
	if !IsValidNick(nick) {
		return
	}

	for k := range s.channels {
		// Check to see if they're in this channel.
		if _, ok := s.channels[k].users[nick]; !ok {
			continue
		}

		delete(s.channels[k].users, nick)
	}
}

// renameUser renames the user in state, in all locations where relevant.
// Always use state.mu for transaction.
func (s *state) renameUser(from, to string) {
	if !IsValidNick(from) || !IsValidNick(to) {
		return
	}

	for k := range s.channels {
		// Check to see if they're in this channel.
		if _, ok := s.channels[k].users[from]; !ok {
			continue
		}

		// Take the actual reference to the pointer.
		source := *s.channels[k].users[from]

		// Update the nick field (as we not only have a key, but a matching
		// struct field).
		source.Nick = to
		source.LastActive = time.Now()

		// Delete the old reference.
		delete(s.channels[k].users, from)

		// In with the new.
		s.channels[k].users[to] = &source
	}
}

// lookupUsers returns a slice of references to users matching a given
// query. mathType is of "nick", "name", "ident" or "account".
func (s *state) lookupUsers(matchType, toMatch string) []*User {
	var users []*User

	for c := range s.channels {
		for u := range s.channels[c].users {
			switch matchType {
			case "nick":
				if s.channels[c].users[u].Nick == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			case "name":
				if s.channels[c].users[u].Extras.Name == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			case "ident":
				if s.channels[c].users[u].Ident == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			case "account":
				if s.channels[c].users[u].Extras.Account == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			}
		}
	}

	return users
}
<commit_msg>implem,ent state.rate()<commit_after>// Copyright (c) Liam Stanley <me@liamstanley.io>. All rights reserved. Use
// of this source code is governed by the MIT license that can be found in
// the LICENSE file.

package girc

import (
	"fmt"
	"net"
	"strings"
	"sync"
	"time"
)

// state represents the actively-changing variables within the client
// runtime.
type state struct {
	// m is a RW mutex lock, used to guard the state from goroutines causing
	// corruption.
	mu sync.RWMutex

	// reader is the socket buffer reader from the IRC server.
	reader *ircDecoder
	// reader is the socket buffer write to the IRC server.
	writer *ircEncoder
	// conn is a net.Conn reference to the IRC server.
	conn net.Conn

	// lastWrite is used ot keep track of when we last wrote to the server.
	lastWrite time.Time
	// writeDelay is used to keep track of rate limiting of events sent to
	// the server.
	writeDelay time.Duration

	// connected is true if we're actively connected to a server.
	connected bool
	// connTime is the time at which the client has connected to a server.
	connTime *time.Time
	// nick is the tracker for our nickname on the server.
	nick string
	// channels represents all channels we're active in.
	channels map[string]*Channel
	// enabledCap are the capabilities which are enabled for this connection.
	enabledCap []string
	// tmpCap are the capabilties which we share with the server during the
	// last capability check. These will get sent once we have received the
	// last capability list command from the server.
	tmpCap []string
	// serverOptions are the standard capabilities and configurations
	// supported by the server at connection time. This also includes
	// RPL_ISUPPORT entries.
	serverOptions map[string]string
	// motd is the servers message of the day.
	motd string
}

// User represents an IRC user and the state attached to them.
type User struct {
	// Nick is the users current nickname.
	Nick string
	// Ident is the users username/ident. Ident is commonly prefixed with a
	// "~", which indicates that they do not have a identd server setup for
	// authentication.
	Ident string
	// Host is the visible host of the users connection that the server has
	// provided to us for their connection. May not always be accurate due to
	// many networks spoofing/hiding parts of the hostname for privacy
	// reasons.
	Host string

	// FirstSeen represents the first time that the user was seen by the
	// client for the given channel. Only usable if from state, not in past.
	FirstSeen time.Time
	// LastActive represents the last time that we saw the user active,
	// which could be during nickname change, message, channel join, etc.
	// Only usable if from state, not in past.
	LastActive time.Time

	// Perms are the user permissions applied to this user that affect the given
	// channel. This supports non-rfc style modes like Admin, Owner, and HalfOp.
	// If you want to easily check if a user has permissions equal or greater
	// than OP, use Perms.IsAdmin().
	Perms UserPerms

	// Extras are things added on by additional tracking methods, which may
	// or may not work on the IRC server in mention.
	Extras struct {
		// Name is the users "realname" or full name. Commonly contains links
		// to the IRC client being used, or something of non-importance. May
		// also be empty if unsupported by the server/tracking is disabled.
		Name string
		// Account refers to the account which the user is authenticated as.
		// This differs between each network (e.g. usually Nickserv, but
		// could also be something like Undernet). May also be empty if
		// unsupported by the server/tracking is disabled.
		Account string
		// Away refers to the away status of the user. An empty string
		// indicates that they are active, otherwise the string is what they
		// set as their away message. May also be empty if unsupported by the
		// server/tracking is disabled.
		Away string
	}
}

// Message returns an event which can be used to send a response to the user
// as a private message.
func (u *User) Message(message string) *Event {
	return &Event{Command: PRIVMSG, Params: []string{u.Nick}, Trailing: message}
}

// Messagef returns an event which can be used to send a response to the user
// as a private message. format is a printf format string, which a's
// arbitrary arguments will be passed to.
func (u *User) Messagef(format string, a ...interface{}) *Event {
	return u.Message(fmt.Sprintf(format, a...))
}

// MessageTo returns an event which can be used to send a response to the
// user in a channel as a private message.
func (u *User) MessageTo(channel, message string) *Event {
	return &Event{Command: PRIVMSG, Params: []string{u.Nick}, Trailing: channel + ": " + message}
}

// MessageTof returns an event which can be used to send a response to the
// channel. format is a printf format string, which a's arbitrary arguments
// will be passed to.
func (u *User) MessageTof(channel, format string, a ...interface{}) *Event {
	return u.MessageTo(channel, fmt.Sprintf(format, a...))
}

// Lifetime represents the amount of time that has passed since we have first
// seen the user.
func (u *User) Lifetime() time.Duration {
	return time.Since(u.FirstSeen)
}

// Active represents the the amount of time that has passed since we have
// last seen the user.
func (u *User) Active() time.Duration {
	return time.Since(u.LastActive)
}

// IsActive returns true if they were active within the last 30 minutes.
func (u *User) IsActive() bool {
	return u.Active() < (time.Minute * 30)
}

// Channel represents an IRC channel and the state attached to it.
type Channel struct {
	// Name of the channel. Must be rfc compliant. Always represented as
	// lower-case, to ensure that the channel is only being tracked once.
	Name string
	// Topic of the channel.
	Topic string
	// users represents the users that we can currently see within the
	// channel.
	users map[string]*User
	// Joined represents the first time that the client joined the channel.
	Joined time.Time
	// Modes are the known channel modes that the bot has captured.
	Modes CModes
}

// Message returns an event which can be used to send a response to the channel.
func (c *Channel) Message(message string) *Event {
	return &Event{Command: PRIVMSG, Params: []string{c.Name}, Trailing: message}
}

// Messagef returns an event which can be used to send a response to the
// channel. format is a printf format string, which a's arbitrary arguments
// will be passed to.
func (c *Channel) Messagef(format string, a ...interface{}) *Event {
	return c.Message(fmt.Sprintf(format, a...))
}

// Lifetime represents the amount of time that has passed since we have first
// joined the channel.
func (c *Channel) Lifetime() time.Duration {
	return time.Since(c.Joined)
}

// newState returns a clean client state.
func newState() *state {
	s := &state{}

	s.channels = make(map[string]*Channel)
	s.serverOptions = make(map[string]string)
	s.connected = false

	return s
}

// createChanIfNotExists creates the channel in state, if not already done.
// Always use state.mu for transaction.
func (s *state) createChanIfNotExists(name string) (channel *Channel) {
	// Not a valid channel.
	if !IsValidChannel(name) {
		return nil
	}

	supported := s.chanModes()
	prefixes, _ := parsePrefixes(s.userPrefixes())

	name = strings.ToLower(name)
	if _, ok := s.channels[name]; !ok {
		channel = &Channel{
			Name:   name,
			users:  make(map[string]*User),
			Joined: time.Now(),
			Modes:  newCModes(supported, prefixes),
		}
		s.channels[name] = channel
	} else {
		channel = s.channels[name]
	}

	return channel
}

// deleteChannel removes the channel from state, if not already done. Always
// use state.mu for transaction.
func (s *state) deleteChannel(name string) {
	channel := s.createChanIfNotExists(name)
	if channel == nil {
		return
	}

	if _, ok := s.channels[channel.Name]; ok {
		delete(s.channels, channel.Name)
	}
}

// lookupChannel returns a reference to a channel with a given case-insensitive
// name. nil returned if no results found.
func (s *state) lookupChannel(name string) *Channel {
	if !IsValidChannel(name) {
		return nil
	}

	return s.channels[strings.ToLower(name)]
}

// createUserIfNotExists creates the channel and user in state, if not already
// done. Always use state.mu for transaction.
func (s *state) createUserIfNotExists(channelName, nick string) (user *User) {
	if !IsValidNick(nick) {
		return nil
	}

	channel := s.createChanIfNotExists(channelName)
	if channel == nil {
		return nil
	}

	if _, ok := channel.users[nick]; ok {
		channel.users[nick].LastActive = time.Now()
		return channel.users[nick]
	}

	user = &User{Nick: nick, FirstSeen: time.Now(), LastActive: time.Now()}
	channel.users[nick] = user

	return user
}

// deleteUser removes the user from channel state. Always use state.mu for
// transaction.
func (s *state) deleteUser(nick string) {
	if !IsValidNick(nick) {
		return
	}

	for k := range s.channels {
		// Check to see if they're in this channel.
		if _, ok := s.channels[k].users[nick]; !ok {
			continue
		}

		delete(s.channels[k].users, nick)
	}
}

// renameUser renames the user in state, in all locations where relevant.
// Always use state.mu for transaction.
func (s *state) renameUser(from, to string) {
	if !IsValidNick(from) || !IsValidNick(to) {
		return
	}

	for k := range s.channels {
		// Check to see if they're in this channel.
		if _, ok := s.channels[k].users[from]; !ok {
			continue
		}

		// Take the actual reference to the pointer.
		source := *s.channels[k].users[from]

		// Update the nick field (as we not only have a key, but a matching
		// struct field).
		source.Nick = to
		source.LastActive = time.Now()

		// Delete the old reference.
		delete(s.channels[k].users, from)

		// In with the new.
		s.channels[k].users[to] = &source
	}
}

// lookupUsers returns a slice of references to users matching a given
// query. mathType is of "nick", "name", "ident" or "account".
func (s *state) lookupUsers(matchType, toMatch string) []*User {
	var users []*User

	for c := range s.channels {
		for u := range s.channels[c].users {
			switch matchType {
			case "nick":
				if s.channels[c].users[u].Nick == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			case "name":
				if s.channels[c].users[u].Extras.Name == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			case "ident":
				if s.channels[c].users[u].Ident == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			case "account":
				if s.channels[c].users[u].Extras.Account == toMatch {
					users = append(users, s.channels[c].users[u])
					continue
				}
			}
		}
	}

	return users
}

// rate allows limiting events based on how frequent the event is being sent,
// as well as how many characters each event has.
func (s *state) rate(chars int) time.Duration {
	_time := time.Second + ((time.Duration(chars) * time.Second) / 100)
	elapsed := time.Now().Sub(s.lastWrite)
	if s.writeDelay += _time - elapsed; s.writeDelay < 0 {
		s.writeDelay = 0
	}

	if s.writeDelay > (8 * time.Second) {
		return _time
	}

	return 0
}
<|endoftext|>


<commit_before>package instance

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/pivotal-pez/haas-broker/handlers/catalog"
	"github.com/pivotal-pez/pezdispenser/pdclient"
)

//GetHandler - this is the handler that will be used for polling async
//provisioning status by the service broker
func (s *InstanceCreator) GetHandler(w http.ResponseWriter, req *http.Request) {
	responseBody := `{
		"state": "succeeded",
		"description": "Creating service (100% complete)."
	}`
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, responseBody)
}

//PutHandler - this is the actual handler method that will be used for the
//incoming request
func (s *InstanceCreator) PutHandler(w http.ResponseWriter, req *http.Request) {
	var (
		err          error
		bodyBytes    []byte
		statusCode   int
		responseBody string
	)
	s.parsePutVars(req)
	if bodyBytes, err = ioutil.ReadAll(req.Body); err == nil {

		if err = json.Unmarshal(bodyBytes, &s.Model); err == nil {
			var (
				leaseRes pdclient.LeaseCreateResponseBody
			)
			client := pdclient.NewClient(s.Dispenser.ApiKey, s.Dispenser.URL, s.ClientDoer)
			inventoryID := fmt.Sprintf("%s-%s", s.Model.OrganizationGUID, s.Model.SpaceGUID)

			if leaseRes, _, err = client.PostLease(s.Model.ServiceID, inventoryID, s.getPlanName(), 14); err == nil {
				s.Model.TaskGUID = leaseRes.ID
				s.Model.Save(s.Collection)
				statusCode = http.StatusAccepted
				responseBody = fmt.Sprintf(`{"dashboard_url": "%s"}`, DashboardUrl)
			}
		}
	}

	if err != nil {
		statusCode = http.StatusNotAcceptable
		responseBody = fmt.Sprintf(`{"error_message": "%s"}`, err.Error())
	}
	w.WriteHeader(statusCode)
	fmt.Fprintf(w, responseBody)
}

func (s *InstanceCreator) parsePutVars(req *http.Request) {
	vars := mux.Vars(req)
	s.Model.InstanceID = vars["instance_id"]
}

func (s *InstanceCreator) getPlanName() string {
	return catalog.PlanGUIDMap[s.Model.PlanID]
}
<commit_msg>[#110117492] fixing type assignment change in new client<commit_after>package instance

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/pivotal-pez/haas-broker/handlers/catalog"
	"github.com/pivotal-pez/pezdispenser/pdclient"
)

//GetHandler - this is the handler that will be used for polling async
//provisioning status by the service broker
func (s *InstanceCreator) GetHandler(w http.ResponseWriter, req *http.Request) {
	responseBody := `{
		"state": "succeeded",
		"description": "Creating service (100% complete)."
	}`
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, responseBody)
}

//PutHandler - this is the actual handler method that will be used for the
//incoming request
func (s *InstanceCreator) PutHandler(w http.ResponseWriter, req *http.Request) {
	var (
		err          error
		bodyBytes    []byte
		statusCode   int
		responseBody string
	)
	s.parsePutVars(req)
	if bodyBytes, err = ioutil.ReadAll(req.Body); err == nil {

		if err = json.Unmarshal(bodyBytes, &s.Model); err == nil {
			var (
				leaseRes pdclient.TaskResponse
			)
			client := pdclient.NewClient(s.Dispenser.ApiKey, s.Dispenser.URL, s.ClientDoer)
			inventoryID := fmt.Sprintf("%s-%s", s.Model.OrganizationGUID, s.Model.SpaceGUID)

			if leaseRes, _, err = client.PostLease(s.Model.ServiceID, inventoryID, s.getPlanName(), 14); err == nil {
				s.Model.TaskGUID = leaseRes.ID
				s.Model.Save(s.Collection)
				statusCode = http.StatusAccepted
				responseBody = fmt.Sprintf(`{"dashboard_url": "%s"}`, DashboardUrl)
			}
		}
	}

	if err != nil {
		statusCode = http.StatusNotAcceptable
		responseBody = fmt.Sprintf(`{"error_message": "%s"}`, err.Error())
	}
	w.WriteHeader(statusCode)
	fmt.Fprintf(w, responseBody)
}

func (s *InstanceCreator) parsePutVars(req *http.Request) {
	vars := mux.Vars(req)
	s.Model.InstanceID = vars["instance_id"]
}

func (s *InstanceCreator) getPlanName() string {
	return catalog.PlanGUIDMap[s.Model.PlanID]
}
<|endoftext|>


<commit_before>package updater

import (
	"fmt"
	"log"
	"runtime"

	update "github.com/inconshreveable/go-update"
)

func updateURL() string {
	// TODO: Use HTTPS.
	return fmt.Sprintf("http://zmon.org/static/%v/%v/zmon", runtime.GOOS, runtime.GOARCH)
}

// SelfUpdate updates the zmon binary. It has several limitations:
//
// - It always performs updates, unconditionally.
//
// - It downloads the entire binary, not patches.
//
// - Binaries are not compressed.
//
// - There is no forced shutdown of old binaries.
func SelfUpdate() error {
	url := updateURL()
	log.Println("Updating zmon binary from", url)
	err, errRecover := update.New().FromUrl(updateURL())
	if err != nil {
		if errRecover != nil {
			return fmt.Errorf("WARNING: Update failed and could recover the old binary%v", err)
		}
		return fmt.Errorf("Update failed: %v\n", err)
	}
	log.Println("Update succeeded")
	return nil
}
<commit_msg>Updater fix<commit_after>package updater

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

	update "github.com/inconshreveable/go-update"
)

func updateURL() string {
	// TODO: Use HTTPS.
	return fmt.Sprintf("http://zmon.org/static/%v/%v/zmon", runtime.GOOS, runtime.GOARCH)
}

// SelfUpdate updates the zmon binary. It has several limitations:
//
// - It always performs updates, unconditionally.
//
// - It downloads the entire binary, not patches.
//
// - Binaries are not compressed.
//
// - There is no forced shutdown of old binaries.
func SelfUpdate() error {
	resp, err := http.Get(updateURL())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if err := update.Apply(resp.Body, update.Options{}); err != nil {
		return fmt.Errorf("Update failed: %v\n", err)
	}
	log.Println("Update succeeded")
	return nil
}
<|endoftext|>


<commit_before>package parse

import "strings"

const (
	typeSep     = " "
	keyValueSep = "="
	valuesSep   = ","
	builtins    = "BUILTINS"
)

// TypeSet turns an array of arguments into a []map[string]string
// that can be given to Parse for it to do its magic.
//
// Acceptable args are:
//
//     Person=man
//     Person=man Animal=dog
//     Person=man Animal=dog Animal2=cat
//     Person=man,woman Animal=dog,cat
//     Person=man,woman,child Animal=dog,cat Place=london,paris
func TypeSet(arg string) ([]map[string]string, error) {

	types := make(map[string][]string)
	var keys []string
	for _, pair := range strings.Split(arg, typeSep) {
		segs := strings.Split(pair, keyValueSep)
		if len(segs) != 2 {
			return nil, &errBadTypeArgs{Arg: arg, Message: "Generic=Specific expected"}
		}
		key := segs[0]
		keys = append(keys, key)
		types[key] = make([]string, 0)
		for _, t := range strings.Split(segs[1], valuesSep) {
			if t == builtins {
				types[key] = append(types[key], Builtins...)
			} else {
				types[key] = append(types[key], t)
			}
		}
	}

	cursors := make(map[string]int)
	for _, key := range keys {
		cursors[key] = 0
	}

	outChan := make(chan map[string]string)
	go func() {
		buildTypeSet(keys, 0, cursors, types, outChan)
		close(outChan)
	}()

	var typeSets []map[string]string
	for typeSet := range outChan {
		typeSets = append(typeSets, typeSet)
	}

	return typeSets, nil

}

func buildTypeSet(keys []string, keyI int, cursors map[string]int, types map[string][]string, out chan<- map[string]string) {
	key := keys[keyI]
	for cursors[key] < len(types[key]) {
		if keyI < len(keys)-1 {
			buildTypeSet(keys, keyI+1, copycursors(cursors), types, out)
		} else {
			// build the typeset for this combination
			ts := make(map[string]string)
			for k, vals := range types {
				ts[k] = vals[cursors[k]]
			}
			out <- ts
		}
		cursors[key]++
	}
}

func copycursors(source map[string]int) map[string]int {
	copy := make(map[string]int)
	for k, v := range source {
		copy[k] = v
	}
	return copy
}
<commit_msg>doc tweaks<commit_after>package parse

import "strings"

const (
	typeSep     = " "
	keyValueSep = "="
	valuesSep   = ","
	builtins    = "BUILTINS"
)

// TypeSet turns a type string into a []map[string]string
// that can be given to parse.Types for it to do its magic.
//
// Acceptable args are:
//
//     Person=man
//     Person=man Animal=dog
//     Person=man Animal=dog Animal2=cat
//     Person=man,woman Animal=dog,cat
//     Person=man,woman,child Animal=dog,cat Place=london,paris
func TypeSet(arg string) ([]map[string]string, error) {

	types := make(map[string][]string)
	var keys []string
	for _, pair := range strings.Split(arg, typeSep) {
		segs := strings.Split(pair, keyValueSep)
		if len(segs) != 2 {
			return nil, &errBadTypeArgs{Arg: arg, Message: "Generic=Specific expected"}
		}
		key := segs[0]
		keys = append(keys, key)
		types[key] = make([]string, 0)
		for _, t := range strings.Split(segs[1], valuesSep) {
			if t == builtins {
				types[key] = append(types[key], Builtins...)
			} else {
				types[key] = append(types[key], t)
			}
		}
	}

	cursors := make(map[string]int)
	for _, key := range keys {
		cursors[key] = 0
	}

	outChan := make(chan map[string]string)
	go func() {
		buildTypeSet(keys, 0, cursors, types, outChan)
		close(outChan)
	}()

	var typeSets []map[string]string
	for typeSet := range outChan {
		typeSets = append(typeSets, typeSet)
	}

	return typeSets, nil

}

func buildTypeSet(keys []string, keyI int, cursors map[string]int, types map[string][]string, out chan<- map[string]string) {
	key := keys[keyI]
	for cursors[key] < len(types[key]) {
		if keyI < len(keys)-1 {
			buildTypeSet(keys, keyI+1, copycursors(cursors), types, out)
		} else {
			// build the typeset for this combination
			ts := make(map[string]string)
			for k, vals := range types {
				ts[k] = vals[cursors[k]]
			}
			out <- ts
		}
		cursors[key]++
	}
}

func copycursors(source map[string]int) map[string]int {
	copy := make(map[string]int)
	for k, v := range source {
		copy[k] = v
	}
	return copy
}
<|endoftext|>