<commit_before>package mockclient

import (
	"io"

	"github.com/samalba/dockerclient"
	"github.com/stretchr/testify/mock"
)

type MockClient struct {
	mock.Mock
}

func NewMockClient() *MockClient {
	return &MockClient{}
}

func (client *MockClient) Info() (*dockerclient.Info, error) {
	args := client.Mock.Called()
	return args.Get(0).(*dockerclient.Info), args.Error(1)
}

func (client *MockClient) ListContainers(all bool, size bool, filters string) ([]dockerclient.Container, error) {
	args := client.Mock.Called(all, size, filters)
	return args.Get(0).([]dockerclient.Container), args.Error(1)
}

func (client *MockClient) InspectContainer(id string) (*dockerclient.ContainerInfo, error) {
	args := client.Mock.Called(id)
	return args.Get(0).(*dockerclient.ContainerInfo), args.Error(1)
}

func (client *MockClient) InspectImage(id string) (*dockerclient.ImageInfo, error) {
	args := client.Mock.Called(id)
	return args.Get(0).(*dockerclient.ImageInfo), args.Error(1)
}

func (client *MockClient) CreateContainer(config *dockerclient.ContainerConfig, name string, authConfig *dockerclient.AuthConfig) (string, error) {
	args := client.Mock.Called(config, name, authConfig)
	return args.String(0), args.Error(1)
}

func (client *MockClient) ContainerLogs(id string, options *dockerclient.LogOptions) (io.ReadCloser, error) {
	args := client.Mock.Called(id, options)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) ContainerChanges(id string) ([]*dockerclient.ContainerChanges, error) {
	args := client.Mock.Called(id)
	return args.Get(0).([]*dockerclient.ContainerChanges), args.Error(1)
}

func (client *MockClient) ContainerStats(id string, stopChan <-chan struct{}) (<-chan dockerclient.StatsOrError, error) {
	args := client.Mock.Called(id, stopChan)
	return args.Get(0).(<-chan dockerclient.StatsOrError), args.Error(1)
}

+func (client *MockClient) AttachContainer(id string, options *dockerclient.AttachOptions) (io.ReadCloser, error) {
	args := client.Mock.Called(id, options)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) StartContainer(id string, config *dockerclient.HostConfig) error {
	args := client.Mock.Called(id, config)
	return args.Error(0)
}

func (client *MockClient) StopContainer(id string, timeout int) error {
	args := client.Mock.Called(id, timeout)
	return args.Error(0)
}

func (client *MockClient) RestartContainer(id string, timeout int) error {
	args := client.Mock.Called(id, timeout)
	return args.Error(0)
}

func (client *MockClient) KillContainer(id, signal string) error {
	args := client.Mock.Called(id, signal)
	return args.Error(0)
}

func (client *MockClient) Wait(id string) <-chan dockerclient.WaitResult {
	args := client.Mock.Called(id)
	return args.Get(0).(<-chan dockerclient.WaitResult)
}

func (client *MockClient) MonitorEvents(options *dockerclient.MonitorEventsOptions, stopChan <-chan struct{}) (<-chan dockerclient.EventOrError, error) {
	args := client.Mock.Called(options, stopChan)
	return args.Get(0).(<-chan dockerclient.EventOrError), args.Error(1)
}

func (client *MockClient) StartMonitorEvents(cb dockerclient.Callback, ec chan error, args ...interface{}) {
	client.Mock.Called(cb, ec, args)
}

func (client *MockClient) StopAllMonitorEvents() {
	client.Mock.Called()
}

func (client *MockClient) TagImage(nameOrID string, repo string, tag string, force bool) error {
	args := client.Mock.Called(nameOrID, repo, tag, force)
	return args.Error(0)
}

func (client *MockClient) StartMonitorStats(id string, cb dockerclient.StatCallback, ec chan error, args ...interface{}) {
	client.Mock.Called(id, cb, ec, args)
}

func (client *MockClient) StopAllMonitorStats() {
	client.Mock.Called()
}

func (client *MockClient) Version() (*dockerclient.Version, error) {
	args := client.Mock.Called()
	return args.Get(0).(*dockerclient.Version), args.Error(1)
}

func (client *MockClient) PullImage(name string, auth *dockerclient.AuthConfig) error {
	args := client.Mock.Called(name, auth)
	return args.Error(0)
}

func (client *MockClient) PushImage(name string, tag string, auth *dockerclient.AuthConfig) error {
	args := client.Mock.Called(name, tag, auth)
	return args.Error(0)
}

func (client *MockClient) LoadImage(reader io.Reader) error {
	args := client.Mock.Called(reader)
	return args.Error(0)
}

func (client *MockClient) RemoveContainer(id string, force, volumes bool) error {
	args := client.Mock.Called(id, force, volumes)
	return args.Error(0)
}

func (client *MockClient) ListImages(all bool) ([]*dockerclient.Image, error) {
	args := client.Mock.Called(all)
	return args.Get(0).([]*dockerclient.Image), args.Error(1)
}

func (client *MockClient) RemoveImage(name string, force bool) ([]*dockerclient.ImageDelete, error) {
	args := client.Mock.Called(name, force)
	return args.Get(0).([]*dockerclient.ImageDelete), args.Error(1)
}

func (client *MockClient) SearchImages(query, registry string, authConfig *dockerclient.AuthConfig) ([]dockerclient.ImageSearch, error) {
	args := client.Mock.Called(query, registry, authConfig)
	return args.Get(0).([]dockerclient.ImageSearch), args.Error(1)
}

func (client *MockClient) PauseContainer(name string) error {
	args := client.Mock.Called(name)
	return args.Error(0)
}

func (client *MockClient) UnpauseContainer(name string) error {
	args := client.Mock.Called(name)
	return args.Error(0)
}

func (client *MockClient) ExecCreate(config *dockerclient.ExecConfig) (string, error) {
	args := client.Mock.Called(config)
	return args.String(0), args.Error(1)
}

func (client *MockClient) ExecStart(id string, config *dockerclient.ExecConfig) error {
	args := client.Mock.Called(id, config)
	return args.Error(0)
}

func (client *MockClient) ExecResize(id string, width, height int) error {
	args := client.Mock.Called(id, width, height)
	return args.Error(0)
}

func (client *MockClient) RenameContainer(oldName string, newName string) error {
	args := client.Mock.Called(oldName, newName)
	return args.Error(0)
}

func (client *MockClient) ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error) {
	args := client.Mock.Called(source, repository, tag, tar)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) BuildImage(image *dockerclient.BuildImage) (io.ReadCloser, error) {
	args := client.Mock.Called(image)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) ListVolumes() ([]*dockerclient.Volume, error) {
	args := client.Mock.Called()
	return args.Get(0).([]*dockerclient.Volume), args.Error(1)
}

func (client *MockClient) RemoveVolume(name string) error {
	args := client.Mock.Called(name)
	return args.Error(0)
}

func (client *MockClient) CreateVolume(request *dockerclient.VolumeCreateRequest) (*dockerclient.Volume, error) {
	args := client.Mock.Called(request)
	return args.Get(0).(*dockerclient.Volume), args.Error(1)
}

func (client *MockClient) ListNetworks(filters string) ([]*dockerclient.NetworkResource, error) {
	args := client.Mock.Called(filters)
	return args.Get(0).([]*dockerclient.NetworkResource), args.Error(1)
}

func (client *MockClient) InspectNetwork(id string) (*dockerclient.NetworkResource, error) {
	args := client.Mock.Called(id)
	return args.Get(0).(*dockerclient.NetworkResource), args.Error(1)
}

func (client *MockClient) CreateNetwork(config *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) {
	args := client.Mock.Called(config)
	return args.Get(0).(*dockerclient.NetworkCreateResponse), args.Error(1)
}

func (client *MockClient) ConnectNetwork(id, container string) error {
	args := client.Mock.Called(id, container)
	return args.Error(0)
}

func (client *MockClient) DisconnectNetwork(id, container string, force bool) error {
	args := client.Mock.Called(id, container, force)
	return args.Error(0)
}

func (client *MockClient) RemoveNetwork(id string) error {
	args := client.Mock.Called(id)
	return args.Error(0)
}<commit_msg>fix mock.go<commit_after>package mockclient

import (
	"io"

	"github.com/samalba/dockerclient"
	"github.com/stretchr/testify/mock"
)

type MockClient struct {
	mock.Mock
}

func NewMockClient() *MockClient {
	return &MockClient{}
}

func (client *MockClient) Info() (*dockerclient.Info, error) {
	args := client.Mock.Called()
	return args.Get(0).(*dockerclient.Info), args.Error(1)
}

func (client *MockClient) ListContainers(all bool, size bool, filters string) ([]dockerclient.Container, error) {
	args := client.Mock.Called(all, size, filters)
	return args.Get(0).([]dockerclient.Container), args.Error(1)
}

func (client *MockClient) InspectContainer(id string) (*dockerclient.ContainerInfo, error) {
	args := client.Mock.Called(id)
	return args.Get(0).(*dockerclient.ContainerInfo), args.Error(1)
}

func (client *MockClient) InspectImage(id string) (*dockerclient.ImageInfo, error) {
	args := client.Mock.Called(id)
	return args.Get(0).(*dockerclient.ImageInfo), args.Error(1)
}

func (client *MockClient) CreateContainer(config *dockerclient.ContainerConfig, name string, authConfig *dockerclient.AuthConfig) (string, error) {
	args := client.Mock.Called(config, name, authConfig)
	return args.String(0), args.Error(1)
}

func (client *MockClient) ContainerLogs(id string, options *dockerclient.LogOptions) (io.ReadCloser, error) {
	args := client.Mock.Called(id, options)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) ContainerChanges(id string) ([]*dockerclient.ContainerChanges, error) {
	args := client.Mock.Called(id)
	return args.Get(0).([]*dockerclient.ContainerChanges), args.Error(1)
}

func (client *MockClient) ContainerStats(id string, stopChan <-chan struct{}) (<-chan dockerclient.StatsOrError, error) {
	args := client.Mock.Called(id, stopChan)
	return args.Get(0).(<-chan dockerclient.StatsOrError), args.Error(1)
}

func (client *MockClient) AttachContainer(id string, options *dockerclient.AttachOptions) (io.ReadCloser, error) {
	args := client.Mock.Called(id, options)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) StartContainer(id string, config *dockerclient.HostConfig) error {
	args := client.Mock.Called(id, config)
	return args.Error(0)
}

func (client *MockClient) StopContainer(id string, timeout int) error {
	args := client.Mock.Called(id, timeout)
	return args.Error(0)
}

func (client *MockClient) RestartContainer(id string, timeout int) error {
	args := client.Mock.Called(id, timeout)
	return args.Error(0)
}

func (client *MockClient) KillContainer(id, signal string) error {
	args := client.Mock.Called(id, signal)
	return args.Error(0)
}

func (client *MockClient) Wait(id string) <-chan dockerclient.WaitResult {
	args := client.Mock.Called(id)
	return args.Get(0).(<-chan dockerclient.WaitResult)
}

func (client *MockClient) MonitorEvents(options *dockerclient.MonitorEventsOptions, stopChan <-chan struct{}) (<-chan dockerclient.EventOrError, error) {
	args := client.Mock.Called(options, stopChan)
	return args.Get(0).(<-chan dockerclient.EventOrError), args.Error(1)
}

func (client *MockClient) StartMonitorEvents(cb dockerclient.Callback, ec chan error, args ...interface{}) {
	client.Mock.Called(cb, ec, args)
}

func (client *MockClient) StopAllMonitorEvents() {
	client.Mock.Called()
}

func (client *MockClient) TagImage(nameOrID string, repo string, tag string, force bool) error {
	args := client.Mock.Called(nameOrID, repo, tag, force)
	return args.Error(0)
}

func (client *MockClient) StartMonitorStats(id string, cb dockerclient.StatCallback, ec chan error, args ...interface{}) {
	client.Mock.Called(id, cb, ec, args)
}

func (client *MockClient) StopAllMonitorStats() {
	client.Mock.Called()
}

func (client *MockClient) Version() (*dockerclient.Version, error) {
	args := client.Mock.Called()
	return args.Get(0).(*dockerclient.Version), args.Error(1)
}

func (client *MockClient) PullImage(name string, auth *dockerclient.AuthConfig) error {
	args := client.Mock.Called(name, auth)
	return args.Error(0)
}

func (client *MockClient) PushImage(name string, tag string, auth *dockerclient.AuthConfig) error {
	args := client.Mock.Called(name, tag, auth)
	return args.Error(0)
}

func (client *MockClient) LoadImage(reader io.Reader) error {
	args := client.Mock.Called(reader)
	return args.Error(0)
}

func (client *MockClient) RemoveContainer(id string, force, volumes bool) error {
	args := client.Mock.Called(id, force, volumes)
	return args.Error(0)
}

func (client *MockClient) ListImages(all bool) ([]*dockerclient.Image, error) {
	args := client.Mock.Called(all)
	return args.Get(0).([]*dockerclient.Image), args.Error(1)
}

func (client *MockClient) RemoveImage(name string, force bool) ([]*dockerclient.ImageDelete, error) {
	args := client.Mock.Called(name, force)
	return args.Get(0).([]*dockerclient.ImageDelete), args.Error(1)
}

func (client *MockClient) SearchImages(query, registry string, authConfig *dockerclient.AuthConfig) ([]dockerclient.ImageSearch, error) {
	args := client.Mock.Called(query, registry, authConfig)
	return args.Get(0).([]dockerclient.ImageSearch), args.Error(1)
}

func (client *MockClient) PauseContainer(name string) error {
	args := client.Mock.Called(name)
	return args.Error(0)
}

func (client *MockClient) UnpauseContainer(name string) error {
	args := client.Mock.Called(name)
	return args.Error(0)
}

func (client *MockClient) ExecCreate(config *dockerclient.ExecConfig) (string, error) {
	args := client.Mock.Called(config)
	return args.String(0), args.Error(1)
}

func (client *MockClient) ExecStart(id string, config *dockerclient.ExecConfig) error {
	args := client.Mock.Called(id, config)
	return args.Error(0)
}

func (client *MockClient) ExecResize(id string, width, height int) error {
	args := client.Mock.Called(id, width, height)
	return args.Error(0)
}

func (client *MockClient) RenameContainer(oldName string, newName string) error {
	args := client.Mock.Called(oldName, newName)
	return args.Error(0)
}

func (client *MockClient) ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error) {
	args := client.Mock.Called(source, repository, tag, tar)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) BuildImage(image *dockerclient.BuildImage) (io.ReadCloser, error) {
	args := client.Mock.Called(image)
	return args.Get(0).(io.ReadCloser), args.Error(1)
}

func (client *MockClient) ListVolumes() ([]*dockerclient.Volume, error) {
	args := client.Mock.Called()
	return args.Get(0).([]*dockerclient.Volume), args.Error(1)
}

func (client *MockClient) RemoveVolume(name string) error {
	args := client.Mock.Called(name)
	return args.Error(0)
}

func (client *MockClient) CreateVolume(request *dockerclient.VolumeCreateRequest) (*dockerclient.Volume, error) {
	args := client.Mock.Called(request)
	return args.Get(0).(*dockerclient.Volume), args.Error(1)
}

func (client *MockClient) ListNetworks(filters string) ([]*dockerclient.NetworkResource, error) {
	args := client.Mock.Called(filters)
	return args.Get(0).([]*dockerclient.NetworkResource), args.Error(1)
}

func (client *MockClient) InspectNetwork(id string) (*dockerclient.NetworkResource, error) {
	args := client.Mock.Called(id)
	return args.Get(0).(*dockerclient.NetworkResource), args.Error(1)
}

func (client *MockClient) CreateNetwork(config *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) {
	args := client.Mock.Called(config)
	return args.Get(0).(*dockerclient.NetworkCreateResponse), args.Error(1)
}

func (client *MockClient) ConnectNetwork(id, container string) error {
	args := client.Mock.Called(id, container)
	return args.Error(0)
}

func (client *MockClient) DisconnectNetwork(id, container string, force bool) error {
	args := client.Mock.Called(id, container, force)
	return args.Error(0)
}

func (client *MockClient) RemoveNetwork(id string) error {
	args := client.Mock.Called(id)
	return args.Error(0)
}
<|endoftext|>


<commit_before>package server

import (
	"github.com/Sirupsen/logrus"
	"github.com/eternnoir/gbf-bike/bike"
	"github.com/gorilla/websocket"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/pkg/errors"
	"net/http"
	"strconv"
	"strings"
	"time"
)

var log = logrus.New().WithFields(logrus.Fields{
	"system": "GBF-Bike",
	"module": "APIServer",
})

var (
	ErrConvertTimeout = errors.New("Can not convert timeout value")
)
var (
	upgrader = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

var welcomeInfo = map[string]interface{}{
	"welcome": "Welcom use gbf bike.",
	"desc":    "GBF captains need a bike. `gbf-bike` helps captain find raid's room id from twitter.",
	"usage":   "https://github.com/eternnoir/gbf-bike",
	"version": "0.9487",
}

var DefaultTimeout = "5"

func NewApi(port string) *ApiServer {
	e := echo.New()
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"*"},
		AllowMethods: []string{echo.GET},
	}))
	return &ApiServer{hs: e, revChanList: make(map[chan (*bike.BattleInfo)]bool), port: port}
}

type ApiServer struct {
	hs          *echo.Echo
	port        string
	revChanList map[chan (*bike.BattleInfo)]bool
}

func (api *ApiServer) Start() error {
	e := api.hs
	e.GET("/", api.welcome)
	e.GET("/query", api.query)
	e.GET("/ws", api.webSocket)
	e.Logger.Fatal(e.Start(":" + api.port))
	return nil
}

func (api *ApiServer) NewBattleInfo(battleInfo *bike.BattleInfo) error {
	log.Debugf("%#v", battleInfo)
	for infoCh, alive := range api.revChanList {
		if !alive {
			delete(api.revChanList, infoCh)
			continue
		}
		go fireBattleInfo(infoCh, battleInfo)
	}
	return nil
}

func fireBattleInfo(ch chan *bike.BattleInfo, battleInfo *bike.BattleInfo) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Recovery in %#v. ", r)
		}
	}()
	select {
	case ch <- battleInfo:
		log.Debugf("Push battle info to channel %#v", battleInfo)
	}

}

func (api *ApiServer) welcome(c echo.Context) error {
	return c.JSON(http.StatusOK, welcomeInfo)
}
func (api *ApiServer) query(c echo.Context) error {
	// Get team and member from the query string
	level := c.QueryParam("level")
	mobs := c.QueryParam("mobs")
	log.Warn(level, mobs)
	timeoutStr := c.QueryParam("timeout")
	if timeoutStr == "" {
		timeoutStr = DefaultTimeout
	}
	timeout, err := convertTimeout(timeoutStr)
	if err != nil {
		return ErrConvertTimeout
	}
	recCh := make(chan (*bike.BattleInfo))
	api.revChanList[recCh] = true
	stopCh := make(chan bool)
	defer close(stopCh)
	defer close(recCh)
	go func() {
		time.Sleep(time.Second * time.Duration(timeout))
		stopCh <- true
	}()
	result := api.pushBattleToList(level, mobs, recCh, stopCh)

	return c.JSON(http.StatusOK, result)
}

func (api *ApiServer) webSocket(c echo.Context) error {
	ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
	if err != nil {
		log.Error(err.Error())
		return err
	}
	defer ws.Close()
	level := convertStringMap(c.QueryParam("level"))
	mobs := convertStringMap(c.QueryParam("mobs"))
	recCh := make(chan (*bike.BattleInfo))
	defer func() {
		close(recCh)
		api.revChanList[recCh] = false
	}()
	api.revChanList[recCh] = true
	for {
		mission := <-recCh
		if isWantedMission(level, mobs, mission) {
			err := ws.WriteJSON(mission)
			if err != nil {
				log.Errorf("WebSocket write error. %s", err.Error())
				return err
			}
		}
	}
}

func (api *ApiServer) pushBattleToList(level, mobs string, ch chan (*bike.BattleInfo), stopCh chan bool) []*bike.BattleInfo {
	list := make([]*bike.BattleInfo, 0)
	mobMap := convertStringMap(mobs)
	levelMap := convertStringMap(level)
	for {
		select {
		case <-stopCh:
			api.revChanList[ch] = false
			return list
		default:
		}
		bi := <-ch
		if isWantedMission(levelMap, mobMap, bi) {
			log.Debug("Push BattleInfo to list")
			list = append(list, bi)
		}
	}
	return list
}

func isWantedMission(levels, mobs map[string]struct{}, info *bike.BattleInfo) bool {
	return isWantedLevel(levels, info) && isWantedMob(mobs, info)
}

func isWantedMob(mobs map[string]struct{}, info *bike.BattleInfo) bool {
	if len(mobs) == 0 {
		return true
	}
	_, ok := mobs[info.MobName]
	return ok
}

func isWantedLevel(levels map[string]struct{}, info *bike.BattleInfo) bool {
	if len(levels) == 0 {
		return true
	}
	_, ok := levels[info.Level]
	return ok
}

func convertStringMap(mobstr string) map[string]struct{} {
	if mobstr == "" {
		return make(map[string]struct{})
	}
	moblist := strings.Split(mobstr, ",")
	ret := make(map[string]struct{})
	for _, mobname := range moblist {
		ret[mobname] = struct{}{}
	}
	return ret
}

func convertTimeout(timeout string) (int64, error) {
	i, err := strconv.Atoi(timeout)
	if err != nil {
		return int64(0), err
	}
	return int64(i), nil
}
<commit_msg>Remove debug code.<commit_after>package server

import (
	"github.com/Sirupsen/logrus"
	"github.com/eternnoir/gbf-bike/bike"
	"github.com/gorilla/websocket"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/pkg/errors"
	"net/http"
	"strconv"
	"strings"
	"time"
)

var log = logrus.New().WithFields(logrus.Fields{
	"system": "GBF-Bike",
	"module": "APIServer",
})

var (
	ErrConvertTimeout = errors.New("Can not convert timeout value")
)
var (
	upgrader = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

var welcomeInfo = map[string]interface{}{
	"welcome": "Welcom use gbf bike.",
	"desc":    "GBF captains need a bike. `gbf-bike` helps captain find raid's room id from twitter.",
	"usage":   "https://github.com/eternnoir/gbf-bike",
	"version": "0.9487",
}

var DefaultTimeout = "5"

func NewApi(port string) *ApiServer {
	e := echo.New()
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"*"},
		AllowMethods: []string{echo.GET},
	}))
	return &ApiServer{hs: e, revChanList: make(map[chan (*bike.BattleInfo)]bool), port: port}
}

type ApiServer struct {
	hs          *echo.Echo
	port        string
	revChanList map[chan (*bike.BattleInfo)]bool
}

func (api *ApiServer) Start() error {
	e := api.hs
	e.GET("/", api.welcome)
	e.GET("/query", api.query)
	e.GET("/ws", api.webSocket)
	e.Logger.Fatal(e.Start(":" + api.port))
	return nil
}

func (api *ApiServer) NewBattleInfo(battleInfo *bike.BattleInfo) error {
	log.Debugf("%#v", battleInfo)
	for infoCh, alive := range api.revChanList {
		if !alive {
			delete(api.revChanList, infoCh)
			continue
		}
		go fireBattleInfo(infoCh, battleInfo)
	}
	return nil
}

func fireBattleInfo(ch chan *bike.BattleInfo, battleInfo *bike.BattleInfo) {
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("Recovery in %#v. ", r)
		}
	}()
	select {
	case ch <- battleInfo:
		log.Debugf("Push battle info to channel %#v", battleInfo)
	}

}

func (api *ApiServer) welcome(c echo.Context) error {
	return c.JSON(http.StatusOK, welcomeInfo)
}
func (api *ApiServer) query(c echo.Context) error {
	// Get team and member from the query string
	level := c.QueryParam("level")
	mobs := c.QueryParam("mobs")
	timeoutStr := c.QueryParam("timeout")
	if timeoutStr == "" {
		timeoutStr = DefaultTimeout
	}
	timeout, err := convertTimeout(timeoutStr)
	if err != nil {
		return ErrConvertTimeout
	}
	recCh := make(chan (*bike.BattleInfo))
	api.revChanList[recCh] = true
	stopCh := make(chan bool)
	defer close(stopCh)
	defer close(recCh)
	go func() {
		time.Sleep(time.Second * time.Duration(timeout))
		stopCh <- true
	}()
	result := api.pushBattleToList(level, mobs, recCh, stopCh)

	return c.JSON(http.StatusOK, result)
}

func (api *ApiServer) webSocket(c echo.Context) error {
	ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
	if err != nil {
		log.Error(err.Error())
		return err
	}
	defer ws.Close()
	level := convertStringMap(c.QueryParam("level"))
	mobs := convertStringMap(c.QueryParam("mobs"))
	recCh := make(chan (*bike.BattleInfo))
	defer func() {
		close(recCh)
		api.revChanList[recCh] = false
	}()
	api.revChanList[recCh] = true
	for {
		mission := <-recCh
		if isWantedMission(level, mobs, mission) {
			err := ws.WriteJSON(mission)
			if err != nil {
				log.Errorf("WebSocket write error. %s", err.Error())
				return err
			}
		}
	}
}

func (api *ApiServer) pushBattleToList(level, mobs string, ch chan (*bike.BattleInfo), stopCh chan bool) []*bike.BattleInfo {
	list := make([]*bike.BattleInfo, 0)
	mobMap := convertStringMap(mobs)
	levelMap := convertStringMap(level)
	for {
		select {
		case <-stopCh:
			api.revChanList[ch] = false
			return list
		default:
		}
		bi := <-ch
		if isWantedMission(levelMap, mobMap, bi) {
			log.Debug("Push BattleInfo to list")
			list = append(list, bi)
		}
	}
	return list
}

func isWantedMission(levels, mobs map[string]struct{}, info *bike.BattleInfo) bool {
	return isWantedLevel(levels, info) && isWantedMob(mobs, info)
}

func isWantedMob(mobs map[string]struct{}, info *bike.BattleInfo) bool {
	if len(mobs) == 0 {
		return true
	}
	_, ok := mobs[info.MobName]
	return ok
}

func isWantedLevel(levels map[string]struct{}, info *bike.BattleInfo) bool {
	if len(levels) == 0 {
		return true
	}
	_, ok := levels[info.Level]
	return ok
}

func convertStringMap(mobstr string) map[string]struct{} {
	if mobstr == "" {
		return make(map[string]struct{})
	}
	moblist := strings.Split(mobstr, ",")
	ret := make(map[string]struct{})
	for _, mobname := range moblist {
		ret[mobname] = struct{}{}
	}
	return ret
}

func convertTimeout(timeout string) (int64, error) {
	i, err := strconv.Atoi(timeout)
	if err != nil {
		return int64(0), err
	}
	return int64(i), nil
}
<|endoftext|>


<commit_before>package dashboard

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

	"github.com/gohttp/app"
	"github.com/gohttp/logger"
	"github.com/gohttp/serve"

	"github.com/dockerboard/dockerboard/server/controllers"
)

func APIIndex(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Coming soon!\n")
}

func Serve() {
	_, filename, _, _ := runtime.Caller(0)
	// Note config dir
	dir := path.Join(path.Dir(filename), "../client/src")

	app := app.New()
	app.Use(logger.New())
	app.Use(serve.New(dir))
	app.Get("/api", APIIndex)
	app.Get("/api/containers", controllers.NewContainers().Index)
	app.Get("/api/containers/:id", controllers.NewContainers().Show)
	app.Get("/api/images", controllers.NewImages().Index)
	app.Get("/api/images/:id", controllers.NewImages().Show)
	app.Get("/api/apps", controllers.NewApps().Index)
	app.Listen(":3333")
}
<commit_msg>update<commit_after>package dashboard

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

	"github.com/gohttp/app"
	"github.com/gohttp/logger"
	"github.com/gohttp/serve"

	"github.com/dockerboard/dockerboard/server/controllers"
)

func APIIndex(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Coming soon!\n")
}

func Serve() {
	_, filename, _, _ := runtime.Caller(0)
	// Note config dir
	dir := path.Join(path.Dir(filename), "../client/src")

	containersController := controllers.NewContainers()
	imagesController := controllers.NewImages()

	app := app.New()
	app.Use(logger.New())
	app.Use(serve.New(dir))
	app.Get("/api", APIIndex)
	app.Get("/api/containers", containersController.Index)
	app.Get("/api/containers/:id", containersController.Show)
	app.Get("/api/images", imagesController.Index)
	app.Get("/api/images/:id", imagesController.Show)
	app.Get("/api/apps", controllers.NewApps().Index)
	app.Listen(":3333")
}
<|endoftext|>


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

package nvim

import (
	"strconv"
	"strings"

	"github.com/garyburd/neovim-go/vim"
)

// Loclist represents an item in a quickfix list.
type LoclistData struct {
	// Buffer number
	Bufnr int `msgpack:"bufnr,omitempty"`
	// Name of a file; only used when bufnr is not present or it is invalid.
	FileName string `msgpack:"filename,omitempty"`
	// Line number in the file.
	LNum int `msgpack:"lnum,omitempty"`
	// Column number (first column is 1).
	Col int `msgpack:"col,omitempty"`
	// When Vcol is != 0,  Col is visual column.
	VCol int `msgpack:"vcol,omitempty"`
	// Error number.
	Nr int `msgpack:"nr,omitempty"`
	// Search pattern used to locate the error.
	Pattern string `msgpack:"pattern,omitempty"`
	// Description of the error.
	Text string `msgpack:"text,omitempty"`
	// Single-character error type, 'E', 'W', etc.
	Type string `msgpack:"type,omitempty"`
	// Valid is non-zero if this is a recognized error message.
	Valid int `msgpack:"valid,omitempty"`
}

func Loclist(p *vim.Pipeline, loclist []*LoclistData, open bool) error {
	// setloclist({nr}, {list} [, {action}])
	// Call(fname string, result interface{}, args ...interface{}) error
	// if err := v.Call("setloclist", nil, 0, loclist); err != nil {
	// 	return err
	// }
	p.Call("setloclist", nil, 0, loclist)

	if open {
		p.Command("lopen")
	}
	if err := p.Wait(); err != nil {
		return err
	}

	return nil
}

func LoclistClose(v *vim.Vim) error {
	return v.Command("lclose")
}

func SplitPos(pos string) (string, int, int) {
	file := strings.Split(pos, ":")
	line, _ := strconv.ParseInt(file[1], 10, 64)
	col, _ := strconv.ParseInt(file[2], 10, 64)

	return file[0], int(line), int(col)
}
<commit_msg>Remove unused code<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package nvim

import (
	"strconv"
	"strings"

	"github.com/garyburd/neovim-go/vim"
)

// Loclist represents an item in a quickfix list.
type LoclistData struct {
	// Buffer number
	Bufnr int `msgpack:"bufnr,omitempty"`
	// Name of a file; only used when bufnr is not present or it is invalid.
	FileName string `msgpack:"filename,omitempty"`
	// Line number in the file.
	LNum int `msgpack:"lnum,omitempty"`
	// Column number (first column is 1).
	Col int `msgpack:"col,omitempty"`
	// When Vcol is != 0,  Col is visual column.
	VCol int `msgpack:"vcol,omitempty"`
	// Error number.
	Nr int `msgpack:"nr,omitempty"`
	// Search pattern used to locate the error.
	Pattern string `msgpack:"pattern,omitempty"`
	// Description of the error.
	Text string `msgpack:"text,omitempty"`
	// Single-character error type, 'E', 'W', etc.
	Type string `msgpack:"type,omitempty"`
	// Valid is non-zero if this is a recognized error message.
	Valid int `msgpack:"valid,omitempty"`
}

func Loclist(p *vim.Pipeline, loclist []*LoclistData, open bool) error {
	// setloclist({nr}, {list} [, {action}])
	// Call(fname string, result interface{}, args ...interface{}) error
	p.Call("setloclist", nil, 0, loclist)

	if open {
		p.Command("lopen")
	}
	if err := p.Wait(); err != nil {
		return err
	}

	return nil
}

func LoclistClose(v *vim.Vim) error {
	return v.Command("lclose")
}

func SplitPos(pos string) (string, int, int) {
	file := strings.Split(pos, ":")
	line, _ := strconv.ParseInt(file[1], 10, 64)
	col, _ := strconv.ParseInt(file[2], 10, 64)

	return file[0], int(line), int(col)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/Unknwon/goconfig"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/reexec"
	"github.com/golang/glog"
	"github.com/hyperhq/hyperd/daemon"
	"github.com/hyperhq/hyperd/daemon/graphdriver/vbox"
	"github.com/hyperhq/hyperd/server"
	"github.com/hyperhq/hyperd/serverrpc"
	"github.com/hyperhq/hyperd/utils"
	"github.com/hyperhq/runv/driverloader"
	"github.com/hyperhq/runv/factory"
	"github.com/hyperhq/runv/hypervisor"

	runvutils "github.com/hyperhq/runv/lib/utils"
	"github.com/kardianos/osext"
)

type Options struct {
	DisableIptables    bool
	Config             string
	Hosts              string
	Mirrors            string
	InsecureRegistries string
}

func main() {
	if reexec.Init() {
		return
	}

	fnd := flag.Bool("nondaemon", false, "Not daemonize")
	flDisableIptables := flag.Bool("noniptables", false, "Don't enable iptables rules")
	flConfig := flag.String("config", "", "Config file for hyperd")
	flHost := flag.String("host", "", "Host for hyperd")
	flMirrors := flag.String("registry_mirror", "", "Prefered docker registry mirror")
	flInsecureRegistries := flag.String("insecure_registry", "", "Enable insecure registry communication")
	flHelp := flag.Bool("help", false, "Print help message for Hyperd daemon")
	flag.Set("alsologtostderr", "true")
	flag.Set("log_dir", "/var/log/hyper/")
	os.MkdirAll("/var/log/hyper/", 0755)
	flag.Usage = func() { printHelp() }
	flag.Parse()
	if *flHelp == true {
		printHelp()
		return
	}

	if !*fnd {
		path, err := osext.Executable()
		if err != nil {
			fmt.Printf("cannot find self executable path for %s: %v\n", os.Args[0], err)
			os.Exit(-1)
		}

		_, err = runvutils.ExecInDaemon(path, append([]string{os.Args[0], "--nondaemon"}, os.Args[1:]...))
		if err != nil {
			fmt.Println("failed to daemonize hyperd")
			os.Exit(-1)
		}

		return
	}

	var opt = &Options{
		DisableIptables:    *flDisableIptables,
		Config:             *flConfig,
		Hosts:              *flHost,
		Mirrors:            *flMirrors,
		InsecureRegistries: *flInsecureRegistries,
	}

	mainDaemon(opt)
}

func printHelp() {
	var helpMessage = `Usage:
  %s [OPTIONS]

Application Options:
  --nondaemon            Not daemonize
  --config=""            Configuration for %s
  --v=0                  Log level fro V logs
  --log_dir              Log directory
  --host                 Host address and port for hyperd(such as --host=tcp://127.0.0.1:12345)
  --registry_mirror      Prefered docker registry mirror, multiple values separated by a comma
  --insecure_registry    Enable insecure registry communication, multiple values separated by a comma
  --logtostderr          Log to standard error instead of files
  --alsologtostderr      Log to standard error as well as files

Help Options:
  -h, --help             Show this help message

`
	fmt.Printf(helpMessage, os.Args[0], os.Args[0])
}

func mainDaemon(opt *Options) {
	config := opt.Config
	glog.V(1).Infof("The config file is %s", config)
	if config == "" {
		config = "/etc/hyper/config"
	}
	if _, err := os.Stat(config); err != nil {
		if os.IsNotExist(err) {
			glog.Errorf("Can not find config file(%s)", config)
			return
		}
		glog.Errorf(err.Error())
		return
	}

	os.Setenv("HYPER_CONFIG", config)
	cfg, err := goconfig.LoadConfigFile(config)
	if err != nil {
		glog.Errorf("Read config file (%s) failed, %s", config, err.Error())
		return
	}

	hyperRoot, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Root")

	if hyperRoot == "" {
		hyperRoot = "/var/lib/hyper"
	}
	utils.HYPER_ROOT = hyperRoot
	if _, err := os.Stat(hyperRoot); err != nil {
		if err := os.MkdirAll(hyperRoot, 0755); err != nil {
			glog.Errorf(err.Error())
			return
		}
	}

	storageDriver, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "StorageDriver")
	daemon.InitDockerCfg(strings.Split(opt.Mirrors, ","), strings.Split(opt.InsecureRegistries, ","), storageDriver, hyperRoot)
	d, err := daemon.NewDaemon(cfg)
	if err != nil {
		glog.Errorf("The hyperd create failed, %s", err.Error())
		return
	}

	vbox.Register(d)

	serverConfig := &server.Config{}

	defaultHost := "unix:///var/run/hyper.sock"
	Hosts := []string{defaultHost}

	if opt.Hosts != "" {
		Hosts = append(Hosts, opt.Hosts)
	}
	if d.Host != "" {
		Hosts = append(Hosts, d.Host)
	}

	for i := 0; i < len(Hosts); i++ {
		var err error
		if Hosts[i], err = opts.ParseHost(defaultHost, Hosts[i]); err != nil {
			glog.Errorf("error parsing -H %s : %v", Hosts[i], err)
			return
		}

		protoAddr := Hosts[i]
		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
		if len(protoAddrParts) != 2 {
			glog.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
			return
		}
		serverConfig.Addrs = append(serverConfig.Addrs, server.Addr{Proto: protoAddrParts[0], Addr: protoAddrParts[1]})
	}

	api, err := server.New(serverConfig)
	if err != nil {
		glog.Errorf(err.Error())
		return
	}

	api.InitRouters(d)

	driver, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Hypervisor")
	driver = strings.ToLower(driver)
	if hypervisor.HDriver, err = driverloader.Probe(driver); err != nil {
		glog.Warningf("%s", err.Error())
		glog.Errorf("Please specify the correct and available hypervisor, such as 'kvm', 'qemu-kvm',  'libvirt', 'xen', 'qemu', 'vbox' or ''")
		return
	} else {
		d.Hypervisor = driver
		glog.Infof("The hypervisor's driver is %s", driver)
	}

	disableIptables := cfg.MustBool(goconfig.DEFAULT_SECTION, "DisableIptables", false)
	if err = hypervisor.InitNetwork(d.BridgeIface, d.BridgeIP, disableIptables || opt.DisableIptables); err != nil {
		glog.Errorf("InitNetwork failed, %s", err.Error())
		return
	}

	defaultLog, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Logger")
	defaultLogCfg, _ := cfg.GetSection("Log")
	d.DefaultLogCfg(defaultLog, defaultLogCfg)

	// Set the daemon object as the global varibal
	// which will be used for puller and builder
	utils.SetDaemon(d)

	if err := d.Restore(); err != nil {
		glog.Warningf("Fail to restore the previous VM")
		return
	}

	vmFactoryPolicy, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "VmFactoryPolicy")
	d.Factory = factory.NewFromPolicy(d.Kernel, d.Initrd, vmFactoryPolicy)

	rpcHost, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "gRPCHost")
	if rpcHost != "" {
		rpcServer := serverrpc.NewServerRPC(d)
		defer rpcServer.Stop()

		go func() {
			err := rpcServer.Serve(rpcHost)
			if err != nil {
				glog.Fatalf("Hyper serve RPC error: %v", err)
			}
		}()
	}

	// The serve API routine never exits unless an error occurs
	// We need to start it as a goroutine and wait on it so
	// daemon doesn't exit
	serveAPIWait := make(chan error)
	go api.Wait(serveAPIWait)

	stopAll := make(chan os.Signal, 1)
	signal.Notify(stopAll, syscall.SIGINT, syscall.SIGTERM)
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGHUP)

	glog.V(0).Infof("Hyper daemon: %s %s",
		utils.VERSION,
		utils.GITCOMMIT,
	)

	// Daemon is fully initialized and handling API traffic
	// Wait for serve API job to complete
	select {
	case errAPI := <-serveAPIWait:
		// If we have an error here it is unique to API (as daemonErr would have
		// exited the daemon process above)
		if errAPI != nil {
			glog.Warningf("Shutting down due to ServeAPI error: %v", errAPI)
		}
		break
	case <-stop:
		d.DestroyAndKeepVm()
		break
	case <-stopAll:
		d.DestroyAllVm()
		break
	}
	d.Factory.CloseFactory()
	api.Close()
	d.Shutdown()
}
<commit_msg>Fixed mistyped word in Usage<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/Unknwon/goconfig"
	"github.com/docker/docker/opts"
	"github.com/docker/docker/pkg/reexec"
	"github.com/golang/glog"
	"github.com/hyperhq/hyperd/daemon"
	"github.com/hyperhq/hyperd/daemon/graphdriver/vbox"
	"github.com/hyperhq/hyperd/server"
	"github.com/hyperhq/hyperd/serverrpc"
	"github.com/hyperhq/hyperd/utils"
	"github.com/hyperhq/runv/driverloader"
	"github.com/hyperhq/runv/factory"
	"github.com/hyperhq/runv/hypervisor"

	runvutils "github.com/hyperhq/runv/lib/utils"
	"github.com/kardianos/osext"
)

type Options struct {
	DisableIptables    bool
	Config             string
	Hosts              string
	Mirrors            string
	InsecureRegistries string
}

func main() {
	if reexec.Init() {
		return
	}

	fnd := flag.Bool("nondaemon", false, "Not daemonize")
	flDisableIptables := flag.Bool("noniptables", false, "Don't enable iptables rules")
	flConfig := flag.String("config", "", "Config file for hyperd")
	flHost := flag.String("host", "", "Host for hyperd")
	flMirrors := flag.String("registry_mirror", "", "Prefered docker registry mirror")
	flInsecureRegistries := flag.String("insecure_registry", "", "Enable insecure registry communication")
	flHelp := flag.Bool("help", false, "Print help message for Hyperd daemon")
	flag.Set("alsologtostderr", "true")
	flag.Set("log_dir", "/var/log/hyper/")
	os.MkdirAll("/var/log/hyper/", 0755)
	flag.Usage = func() { printHelp() }
	flag.Parse()
	if *flHelp == true {
		printHelp()
		return
	}

	if !*fnd {
		path, err := osext.Executable()
		if err != nil {
			fmt.Printf("cannot find self executable path for %s: %v\n", os.Args[0], err)
			os.Exit(-1)
		}

		_, err = runvutils.ExecInDaemon(path, append([]string{os.Args[0], "--nondaemon"}, os.Args[1:]...))
		if err != nil {
			fmt.Println("failed to daemonize hyperd")
			os.Exit(-1)
		}

		return
	}

	var opt = &Options{
		DisableIptables:    *flDisableIptables,
		Config:             *flConfig,
		Hosts:              *flHost,
		Mirrors:            *flMirrors,
		InsecureRegistries: *flInsecureRegistries,
	}

	mainDaemon(opt)
}

func printHelp() {
	var helpMessage = `Usage:
  %s [OPTIONS]

Application Options:
  --nondaemon            Not daemonize
  --config=""            Configuration for %s
  --v=0                  Log level for V logs
  --log_dir              Log directory
  --host                 Host address and port for hyperd(such as --host=tcp://127.0.0.1:12345)
  --registry_mirror      Prefered docker registry mirror, multiple values separated by a comma
  --insecure_registry    Enable insecure registry communication, multiple values separated by a comma
  --logtostderr          Log to standard error instead of files
  --alsologtostderr      Log to standard error as well as files

Help Options:
  -h, --help             Show this help message

`
	fmt.Printf(helpMessage, os.Args[0], os.Args[0])
}

func mainDaemon(opt *Options) {
	config := opt.Config
	glog.V(1).Infof("The config file is %s", config)
	if config == "" {
		config = "/etc/hyper/config"
	}
	if _, err := os.Stat(config); err != nil {
		if os.IsNotExist(err) {
			glog.Errorf("Can not find config file(%s)", config)
			return
		}
		glog.Errorf(err.Error())
		return
	}

	os.Setenv("HYPER_CONFIG", config)
	cfg, err := goconfig.LoadConfigFile(config)
	if err != nil {
		glog.Errorf("Read config file (%s) failed, %s", config, err.Error())
		return
	}

	hyperRoot, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Root")

	if hyperRoot == "" {
		hyperRoot = "/var/lib/hyper"
	}
	utils.HYPER_ROOT = hyperRoot
	if _, err := os.Stat(hyperRoot); err != nil {
		if err := os.MkdirAll(hyperRoot, 0755); err != nil {
			glog.Errorf(err.Error())
			return
		}
	}

	storageDriver, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "StorageDriver")
	daemon.InitDockerCfg(strings.Split(opt.Mirrors, ","), strings.Split(opt.InsecureRegistries, ","), storageDriver, hyperRoot)
	d, err := daemon.NewDaemon(cfg)
	if err != nil {
		glog.Errorf("The hyperd create failed, %s", err.Error())
		return
	}

	vbox.Register(d)

	serverConfig := &server.Config{}

	defaultHost := "unix:///var/run/hyper.sock"
	Hosts := []string{defaultHost}

	if opt.Hosts != "" {
		Hosts = append(Hosts, opt.Hosts)
	}
	if d.Host != "" {
		Hosts = append(Hosts, d.Host)
	}

	for i := 0; i < len(Hosts); i++ {
		var err error
		if Hosts[i], err = opts.ParseHost(defaultHost, Hosts[i]); err != nil {
			glog.Errorf("error parsing -H %s : %v", Hosts[i], err)
			return
		}

		protoAddr := Hosts[i]
		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
		if len(protoAddrParts) != 2 {
			glog.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
			return
		}
		serverConfig.Addrs = append(serverConfig.Addrs, server.Addr{Proto: protoAddrParts[0], Addr: protoAddrParts[1]})
	}

	api, err := server.New(serverConfig)
	if err != nil {
		glog.Errorf(err.Error())
		return
	}

	api.InitRouters(d)

	driver, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Hypervisor")
	driver = strings.ToLower(driver)
	if hypervisor.HDriver, err = driverloader.Probe(driver); err != nil {
		glog.Warningf("%s", err.Error())
		glog.Errorf("Please specify the correct and available hypervisor, such as 'kvm', 'qemu-kvm',  'libvirt', 'xen', 'qemu', 'vbox' or ''")
		return
	} else {
		d.Hypervisor = driver
		glog.Infof("The hypervisor's driver is %s", driver)
	}

	disableIptables := cfg.MustBool(goconfig.DEFAULT_SECTION, "DisableIptables", false)
	if err = hypervisor.InitNetwork(d.BridgeIface, d.BridgeIP, disableIptables || opt.DisableIptables); err != nil {
		glog.Errorf("InitNetwork failed, %s", err.Error())
		return
	}

	defaultLog, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "Logger")
	defaultLogCfg, _ := cfg.GetSection("Log")
	d.DefaultLogCfg(defaultLog, defaultLogCfg)

	// Set the daemon object as the global varibal
	// which will be used for puller and builder
	utils.SetDaemon(d)

	if err := d.Restore(); err != nil {
		glog.Warningf("Fail to restore the previous VM")
		return
	}

	vmFactoryPolicy, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "VmFactoryPolicy")
	d.Factory = factory.NewFromPolicy(d.Kernel, d.Initrd, vmFactoryPolicy)

	rpcHost, _ := cfg.GetValue(goconfig.DEFAULT_SECTION, "gRPCHost")
	if rpcHost != "" {
		rpcServer := serverrpc.NewServerRPC(d)
		defer rpcServer.Stop()

		go func() {
			err := rpcServer.Serve(rpcHost)
			if err != nil {
				glog.Fatalf("Hyper serve RPC error: %v", err)
			}
		}()
	}

	// The serve API routine never exits unless an error occurs
	// We need to start it as a goroutine and wait on it so
	// daemon doesn't exit
	serveAPIWait := make(chan error)
	go api.Wait(serveAPIWait)

	stopAll := make(chan os.Signal, 1)
	signal.Notify(stopAll, syscall.SIGINT, syscall.SIGTERM)
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGHUP)

	glog.V(0).Infof("Hyper daemon: %s %s",
		utils.VERSION,
		utils.GITCOMMIT,
	)

	// Daemon is fully initialized and handling API traffic
	// Wait for serve API job to complete
	select {
	case errAPI := <-serveAPIWait:
		// If we have an error here it is unique to API (as daemonErr would have
		// exited the daemon process above)
		if errAPI != nil {
			glog.Warningf("Shutting down due to ServeAPI error: %v", errAPI)
		}
		break
	case <-stop:
		d.DestroyAndKeepVm()
		break
	case <-stopAll:
		d.DestroyAllVm()
		break
	}
	d.Factory.CloseFactory()
	api.Close()
	d.Shutdown()
}
<|endoftext|>


<commit_before>package rootio

// Class represents a ROOT class.
// Class instances are created by a ClassFactory.
type Class interface {
	// GetCheckSum gets the check sum for this ROOT class
	//CheckSum() int

	// Members returns the list of members for this ROOT class
	Members() []Member

	// Version returns the version number for this ROOT class
	Version() int

	// Name returns the ROOT class name for this ROOT class
	Name() string
}

// Member represents a single member of a ROOT class
type Member interface {
	// GetArrayDim returns the dimension of the array (if any)
	ArrayDim() int

	// GetComment returns the comment associated with this member
	Comment() string

	// Name returns the name of this member
	Name() string

	// Type returns the class of this member
	Type() Class

	// GetValue returns the value of this member
	//GetValue(o Object) reflect.Value
}

// Object represents a ROOT object
type Object interface {
	// Class returns the ROOT class of this object
	Class() string

	// Name returns the name of this ROOT object
	Name() string

	// Title returns the title of this ROOT object
	Title() string
}

// ClassFactory creates ROOT classes
type ClassFactory interface {
	Create(name string) Class
}

// EOF
<commit_msg>ifaces: add Directory, ROOTUnmarshaler and ROOTMarshaler interfaces<commit_after>package rootio

// Class represents a ROOT class.
// Class instances are created by a ClassFactory.

type Class interface {
	// GetCheckSum gets the check sum for this ROOT class
	//CheckSum() int

	// Members returns the list of members for this ROOT class
	Members() []Member

	// Version returns the version number for this ROOT class
	Version() int

	// Name returns the ROOT class name for this ROOT class
	Name() string
}

// Member represents a single member of a ROOT class
type Member interface {
	// GetArrayDim returns the dimension of the array (if any)
	ArrayDim() int

	// GetComment returns the comment associated with this member
	Comment() string

	// Name returns the name of this member
	Name() string

	// Type returns the class of this member
	Type() Class

	// GetValue returns the value of this member
	//GetValue(o Object) reflect.Value
}

// Object represents a ROOT object
type Object interface {
	// Class returns the ROOT class of this object
	Class() string

	// Name returns the name of this ROOT object
	Name() string

	// Title returns the title of this ROOT object
	Title() string
}

// ClassFactory creates ROOT classes
type ClassFactory interface {
	Create(name string) Class
}

// Directory describes a ROOT directory structure in memory.
type Directory interface {
	// return pointer to object identified by namecycle
	//   namecycle has the format name;cycle
	//   name  = * is illegal, cycle = * is illegal
	//   cycle = "" or cycle = 9999 ==> apply to a memory object
	//
	//   examples:
	//     foo   : get object named foo in memory
	//             if object is not in memory, try with highest cycle from file
	//     foo;1 : get cycle 1 of foo on file
	Get(namecycle string) (Object, error)

	// return whether an object identified by namecycle exists in directory
	//   namecycle has the format name;cycle
	//   name  = * is illegal, cycle = * is illegal
	//   cycle = "" or cycle = 9999 ==> apply to a memory object
	//
	//   examples:
	//     foo   : get object named foo in memory
	//             if object is not in memory, try with highest cycle from file
	//     foo;1 : get cycle 1 of foo on file
	Has(namecycle string) bool
}

// ROOTUnmarshaler is the interface implemented by an object that can
// unmarshal itself from a ROOT buffer
type ROOTUnmarshaler interface {
	UnmarshalROOT(data []byte) error
}

// ROOTMarshaler is the interface implemented by an object that can
// marshal itself into a ROOT buffer
type ROOTMarshaler interface {
	MarshalROOT() (data []byte, err error)
}

// EOF
<|endoftext|>


<commit_before>package igener

import (
	"encoding/binary"
	"fmt"
	"hash/crc32"
	"os"
	"time"
)

type IGener struct {
	machineCode [3]byte
	pidCode     [2]byte
	second      int64
	idChan      chan string
	inc         uint32
}

func NewIGener() <-chan string {
	ig := &IGener{
		second: time.Now().Unix(),
		inc:    0,
		idChan: make(chan string),
	}
	ig.machineCode, ig.pidCode = ig.machinePidEncode()

	go ig.generUniqueId()

	return ig.idChan
}

func (ig *IGener) machinePidEncode() ([3]byte, [2]byte) {
	hostname, _ := os.Hostname()

	buf := [4]byte{}
	binary.BigEndian.PutUint32(buf[:], crc32.ChecksumIEEE([]byte(hostname)))
	machineCode := [3]byte{buf[1], buf[2], buf[3]}

	pid := os.Getpid()
	pidCode := [2]byte{}
	binary.BigEndian.PutUint16(pidCode[:], uint16(pid))

	return machineCode, pidCode
}

func (ig *IGener) timeIncEncode() ([4]byte, [3]byte) {
	now := time.Now().Unix()
	timeEncode := [4]byte{}
	incEncode := [3]byte{}
	buf := [8]byte{}

	if ig.second != now {
		ig.second = now
		ig.inc = 0
	}

	binary.BigEndian.PutUint64(buf[:], uint64(ig.second))
	timeEncode = [4]byte{buf[4], buf[5], buf[6], buf[7]}

	binary.BigEndian.PutUint32(buf[:], uint32(ig.inc))
	incEncode = [3]byte{buf[1], buf[2], buf[3]}
	ig.inc++

	return timeEncode, incEncode
}

func (ig *IGener) generUniqueId(){
	var uniqueId [12]byte
	for {
		timeEncode, incEncode := ig.timeIncEncode()
		var i int = 0
		for _, b := range timeEncode {
			uniqueId[i] = b
			i++
		}

		for _, b := range ig.machineCode {
			uniqueId[i] = b
			i++
		}

		for _, b := range ig.pidCode {
			uniqueId[i] = b
			i++
		}

		for _, b := range incEncode {
			uniqueId[i] = b
			i++
		}

		ig.idChan <- fmt.Sprintf("%x", uniqueId)
	}
}
<commit_msg>use hex instead of fmt.Sprinf<commit_after>package igener

import (
	"encoding/binary"
	"encoding/hex"
	"hash/crc32"
	"os"
	"time"
)

type IGener struct {
	machineCode [3]byte
	pidCode     [2]byte
	second      int64
	idChan      chan string
	inc         uint32
}

func NewIGener() <-chan string {
	ig := &IGener{
		second: time.Now().Unix(),
		inc:    0,
		idChan: make(chan string),
	}
	ig.machineCode, ig.pidCode = ig.machinePidEncode()

	go ig.generUniqueId()

	return ig.idChan
}

func (ig *IGener) machinePidEncode() ([3]byte, [2]byte) {
	hostname, _ := os.Hostname()

	buf := [4]byte{}
	binary.BigEndian.PutUint32(buf[:], crc32.ChecksumIEEE([]byte(hostname)))
	machineCode := [3]byte{buf[1], buf[2], buf[3]}

	pid := os.Getpid()
	pidCode := [2]byte{}
	binary.BigEndian.PutUint16(pidCode[:], uint16(pid))

	return machineCode, pidCode
}

func (ig *IGener) timeIncEncode() ([4]byte, [3]byte) {
	now := time.Now().Unix()
	timeEncode := [4]byte{}
	incEncode := [3]byte{}
	buf := [8]byte{}

	if ig.second != now {
		ig.second = now
		ig.inc = 0
	}

	binary.BigEndian.PutUint64(buf[:], uint64(ig.second))
	timeEncode = [4]byte{buf[4], buf[5], buf[6], buf[7]}

	binary.BigEndian.PutUint32(buf[:], uint32(ig.inc))
	incEncode = [3]byte{buf[1], buf[2], buf[3]}
	ig.inc++

	return timeEncode, incEncode
}

func (ig *IGener) generUniqueId() {
	var uniqueId [12]byte
	for {
		timeEncode, incEncode := ig.timeIncEncode()
		var i int = 0
		for _, b := range timeEncode {
			uniqueId[i] = b
			i++
		}

		for _, b := range ig.machineCode {
			uniqueId[i] = b
			i++
		}

		for _, b := range ig.pidCode {
			uniqueId[i] = b
			i++
		}

		for _, b := range incEncode {
			uniqueId[i] = b
			i++
		}

		ig.idChan <- hex.EncodeToString(uniqueId[:])

	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/google/go-github/github"
	"github.com/pkg/errors"
	"golang.org/x/oauth2"
)

var (
	RelaseNotFound = errors.New("release is not found")
)

type GitHub interface {
	CreateRelease(ctx context.Context, req *github.RepositoryRelease) (*github.RepositoryRelease, error)
	GetRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error)
	DeleteRelease(ctx context.Context, releaseID int) error
	DeleteTag(ctx context.Context, tag string) error

	UploadAsset(ctx context.Context, releaseID int, filename string) (*github.ReleaseAsset, error)
	DeleteAsset(ctx context.Context, assetID int) error
	ListAssets(ctx context.Context, releaseID int) ([]*github.ReleaseAsset, error)

	SetUploadURL(urlStr string) error
}

type GitHubClient struct {
	Owner, Repo string
	*github.Client
}

func NewGitHubClient(owner, repo, token string, urlStr string) (GitHub, error) {
	if len(owner) == 0 {
		return nil, errors.New("missing GitHub repository owner")
	}

	if len(owner) == 0 {
		return nil, errors.New("missing GitHub repository name")
	}

	if len(token) == 0 {
		return nil, errors.New("missing GitHub API token")
	}

	if len(urlStr) == 0 {
		return nil, errors.New("missgig GitHub API URL")
	}

	baseURL, err := url.ParseRequestURI(urlStr)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse Github API URL")
	}

	ts := oauth2.StaticTokenSource(&oauth2.Token{
		AccessToken: token,
	})
	tc := oauth2.NewClient(oauth2.NoContext, ts)

	client := github.NewClient(tc)
	client.BaseURL = baseURL

	return &GitHubClient{
		Owner:  owner,
		Repo:   repo,
		Client: client,
	}, nil
}

func (c *GitHubClient) SetUploadURL(urlStr string) error {
	i := strings.Index(urlStr, "repos/")
	parsedURL, err := url.ParseRequestURI(urlStr[:i])
	if err != nil {
		return errors.Wrap(err, "faield to parse upload URL")
	}

	c.UploadURL = parsedURL
	return nil
}

func (c *GitHubClient) CreateRelease(ctx context.Context, req *github.RepositoryRelease) (*github.RepositoryRelease, error) {

	release, res, err := c.Repositories.CreateRelease(c.Owner, c.Repo, req)
	if err != nil {
		return nil, errors.Wrap(err, "failed to create a release")
	}

	if res.StatusCode != http.StatusCreated {
		return nil, errors.Errorf("create release: invalid status: %s", res.Status)
	}

	return release, nil
}

func (c *GitHubClient) GetRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error) {
	// Check Release is already exist or not
	release, res, err := c.Repositories.GetReleaseByTag(c.Owner, c.Repo, tag)
	if err != nil {
		if res == nil {
			return nil, errors.Wrapf(err, "failed to get release tag: %s", tag)
		}

		// TODO(tcnksm): Handle invalid token
		if res.StatusCode != http.StatusNotFound {
			return nil, errors.Wrapf(err,
				"get release tag: invalid status: %s", res.Status)
		}

		return nil, RelaseNotFound
	}

	return release, nil
}

func (c *GitHubClient) DeleteRelease(ctx context.Context, releaseID int) error {
	res, err := c.Repositories.DeleteRelease(c.Owner, c.Repo, releaseID)
	if err != nil {
		return errors.Wrap(err, "failed to delete release")
	}

	if res.StatusCode != http.StatusNoContent {
		return errors.Errorf("delete release: invalid status: %s", res.Status)
	}

	return nil
}

func (c *GitHubClient) DeleteTag(ctx context.Context, tag string) error {
	ref := fmt.Sprintf("tags/%s", tag)
	res, err := c.Git.DeleteRef(c.Owner, c.Repo, ref)
	if err != nil {
		return errors.Wrapf(err, "failed to delete tag: %s", ref)
	}

	if res.StatusCode != http.StatusNoContent {
		return errors.Errorf("delete tag: invalid status: %s", res.Status)
	}

	return nil
}

func (c *GitHubClient) UploadAsset(ctx context.Context, releaseID int, filename string) (*github.ReleaseAsset, error) {

	filename, err := filepath.Abs(filename)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get abs path")
	}

	f, err := os.Open(filename)
	if err != nil {
		return nil, errors.Wrap(err, "failed to open file")
	}

	opts := &github.UploadOptions{
		// Use base name by default
		Name: filepath.Base(filename),
	}

	asset, res, err := c.Repositories.UploadReleaseAsset(c.Owner, c.Repo, releaseID, opts, f)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to upload release asset: %s", filename)
	}

	switch res.StatusCode {
	case http.StatusCreated:
		return asset, nil
	case 422:
		return nil, errors.Errorf(
			"upload release asset: invalid status code: %s",
			"422 (this is probably because the asset already uploaded)")
	default:
		return nil, errors.Errorf(
			"upload release asset: invalid status code: %s", res.Status)
	}
}

func (c *GitHubClient) DeleteAsset(ctx context.Context, assetID int) error {
	res, err := c.Repositories.DeleteReleaseAsset(c.Owner, c.Repo, assetID)
	if err != nil {
		return errors.Wrap(err, "failed to delete release asset")
	}

	if res.StatusCode != http.StatusNoContent {
		return errors.Errorf("delete release assets: invalid status code: %s", res.Status)
	}

	return nil
}

func (c *GitHubClient) ListAssets(ctx context.Context, releaseID int) ([]*github.ReleaseAsset, error) {
	assets, res, err := c.Repositories.ListReleaseAssets(c.Owner, c.Repo, releaseID, nil)
	if err != nil {
		return nil, errors.Wrap(err, "failed to list assets")
	}

	if res.StatusCode != http.StatusOK {
		return nil, errors.Errorf("list release assets: invalid status code: %s", res.Status)
	}

	return assets, nil
}
<commit_msg>Add pagination to ListAssets call<commit_after>package main

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/google/go-github/github"
	"github.com/pkg/errors"
	"golang.org/x/oauth2"
)

var (
	RelaseNotFound = errors.New("release is not found")
)

type GitHub interface {
	CreateRelease(ctx context.Context, req *github.RepositoryRelease) (*github.RepositoryRelease, error)
	GetRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error)
	DeleteRelease(ctx context.Context, releaseID int) error
	DeleteTag(ctx context.Context, tag string) error

	UploadAsset(ctx context.Context, releaseID int, filename string) (*github.ReleaseAsset, error)
	DeleteAsset(ctx context.Context, assetID int) error
	ListAssets(ctx context.Context, releaseID int) ([]*github.ReleaseAsset, error)

	SetUploadURL(urlStr string) error
}

type GitHubClient struct {
	Owner, Repo string
	*github.Client
}

func NewGitHubClient(owner, repo, token string, urlStr string) (GitHub, error) {
	if len(owner) == 0 {
		return nil, errors.New("missing GitHub repository owner")
	}

	if len(owner) == 0 {
		return nil, errors.New("missing GitHub repository name")
	}

	if len(token) == 0 {
		return nil, errors.New("missing GitHub API token")
	}

	if len(urlStr) == 0 {
		return nil, errors.New("missgig GitHub API URL")
	}

	baseURL, err := url.ParseRequestURI(urlStr)
	if err != nil {
		return nil, errors.Wrap(err, "failed to parse Github API URL")
	}

	ts := oauth2.StaticTokenSource(&oauth2.Token{
		AccessToken: token,
	})
	tc := oauth2.NewClient(oauth2.NoContext, ts)

	client := github.NewClient(tc)
	client.BaseURL = baseURL

	return &GitHubClient{
		Owner:  owner,
		Repo:   repo,
		Client: client,
	}, nil
}

func (c *GitHubClient) SetUploadURL(urlStr string) error {
	i := strings.Index(urlStr, "repos/")
	parsedURL, err := url.ParseRequestURI(urlStr[:i])
	if err != nil {
		return errors.Wrap(err, "faield to parse upload URL")
	}

	c.UploadURL = parsedURL
	return nil
}

func (c *GitHubClient) CreateRelease(ctx context.Context, req *github.RepositoryRelease) (*github.RepositoryRelease, error) {

	release, res, err := c.Repositories.CreateRelease(c.Owner, c.Repo, req)
	if err != nil {
		return nil, errors.Wrap(err, "failed to create a release")
	}

	if res.StatusCode != http.StatusCreated {
		return nil, errors.Errorf("create release: invalid status: %s", res.Status)
	}

	return release, nil
}

func (c *GitHubClient) GetRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error) {
	// Check Release is already exist or not
	release, res, err := c.Repositories.GetReleaseByTag(c.Owner, c.Repo, tag)
	if err != nil {
		if res == nil {
			return nil, errors.Wrapf(err, "failed to get release tag: %s", tag)
		}

		// TODO(tcnksm): Handle invalid token
		if res.StatusCode != http.StatusNotFound {
			return nil, errors.Wrapf(err,
				"get release tag: invalid status: %s", res.Status)
		}

		return nil, RelaseNotFound
	}

	return release, nil
}

func (c *GitHubClient) DeleteRelease(ctx context.Context, releaseID int) error {
	res, err := c.Repositories.DeleteRelease(c.Owner, c.Repo, releaseID)
	if err != nil {
		return errors.Wrap(err, "failed to delete release")
	}

	if res.StatusCode != http.StatusNoContent {
		return errors.Errorf("delete release: invalid status: %s", res.Status)
	}

	return nil
}

func (c *GitHubClient) DeleteTag(ctx context.Context, tag string) error {
	ref := fmt.Sprintf("tags/%s", tag)
	res, err := c.Git.DeleteRef(c.Owner, c.Repo, ref)
	if err != nil {
		return errors.Wrapf(err, "failed to delete tag: %s", ref)
	}

	if res.StatusCode != http.StatusNoContent {
		return errors.Errorf("delete tag: invalid status: %s", res.Status)
	}

	return nil
}

func (c *GitHubClient) UploadAsset(ctx context.Context, releaseID int, filename string) (*github.ReleaseAsset, error) {

	filename, err := filepath.Abs(filename)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get abs path")
	}

	f, err := os.Open(filename)
	if err != nil {
		return nil, errors.Wrap(err, "failed to open file")
	}

	opts := &github.UploadOptions{
		// Use base name by default
		Name: filepath.Base(filename),
	}

	asset, res, err := c.Repositories.UploadReleaseAsset(c.Owner, c.Repo, releaseID, opts, f)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to upload release asset: %s", filename)
	}

	switch res.StatusCode {
	case http.StatusCreated:
		return asset, nil
	case 422:
		return nil, errors.Errorf(
			"upload release asset: invalid status code: %s",
			"422 (this is probably because the asset already uploaded)")
	default:
		return nil, errors.Errorf(
			"upload release asset: invalid status code: %s", res.Status)
	}
}

func (c *GitHubClient) DeleteAsset(ctx context.Context, assetID int) error {
	res, err := c.Repositories.DeleteReleaseAsset(c.Owner, c.Repo, assetID)
	if err != nil {
		return errors.Wrap(err, "failed to delete release asset")
	}

	if res.StatusCode != http.StatusNoContent {
		return errors.Errorf("delete release assets: invalid status code: %s", res.Status)
	}

	return nil
}

func (c *GitHubClient) ListAssets(ctx context.Context, releaseID int) ([]*github.ReleaseAsset, error) {
	result := []*github.ReleaseAsset{}
	page := 1

	for {
		assets, res, err := c.Repositories.ListReleaseAssets(c.Owner, c.Repo, releaseID, &github.ListOptions{Page: page})
		if err != nil {
			return nil, errors.Wrap(err, "failed to list assets")
		}

		if res.StatusCode != http.StatusOK {
			return nil, errors.Errorf("list release assets: invalid status code: %s", res.Status)
		}

		result = append(result, assets...)

		if res.NextPage <= page {
			break
		}

		page = res.NextPage
	}

	return result, nil
}
<|endoftext|>


<commit_before>// Package gitter is a Go client library for the Gitter API.
//
// Author: sromku
package gitter

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/mreiferson/go-httpclient"
)

var (
	apiBaseURL    = "https://api.gitter.im/v1/"
	streamBaseURL = "https://stream.gitter.im/v1/"
	fayeBaseURL   = "https://ws.gitter.im/faye"
)

type Gitter struct {
	config struct {
		apiBaseURL    string
		streamBaseURL string
		token         string
		client        *http.Client
	}
	debug     bool
	logWriter io.Writer
}

// New initializes the Gitter API client
//
// For example:
//  api := gitter.New("YOUR_ACCESS_TOKEN")
func New(token string) *Gitter {

	transport := &httpclient.Transport{
		ConnectTimeout:   5 * time.Second,
		ReadWriteTimeout: 40 * time.Second,
	}
	defer transport.Close()

	s := &Gitter{}
	s.config.apiBaseURL = apiBaseURL
	s.config.streamBaseURL = streamBaseURL
	s.config.token = token
	s.config.client = &http.Client{
		Transport: transport,
	}
	return s
}

// SetClient sets a custom http client. Can be useful in App Engine case.
func (gitter *Gitter) SetClient(client *http.Client) {
	gitter.config.client = client
}

// GetUser returns the current user
func (gitter *Gitter) GetUser() (*User, error) {

	var users []User
	response, err := gitter.get(gitter.config.apiBaseURL + "user")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &users)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	if len(users) > 0 {
		return &users[0], nil
	}

	err = APIError{What: "Failed to retrieve current user"}
	gitter.log(err)
	return nil, err
}

// GetUserRooms returns a list of Rooms the user is part of
func (gitter *Gitter) GetUserRooms(userID string) ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(gitter.config.apiBaseURL + "user/" + userID + "/rooms")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return rooms, nil
}

// GetRooms returns a list of rooms the current user is in
func (gitter *Gitter) GetRooms() ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return rooms, nil
}

// GetRoom returns a room with the passed id
func (gitter *Gitter) GetRoom(roomID string) (*Room, error) {

	var room Room
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms/" + roomID)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &room)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return &room, nil
}

// GetMessages returns a list of messages in a room.
// Pagination is optional. You can pass nil or specific pagination params.
func (gitter *Gitter) GetMessages(roomID string, params *Pagination) ([]Message, error) {

	var messages []Message
	url := gitter.config.apiBaseURL + "rooms/" + roomID + "/chatMessages"
	if params != nil {
		url += "?" + params.encode()
	}
	response, err := gitter.get(url)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &messages)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return messages, nil
}

// GetMessage returns a message in a room.
func (gitter *Gitter) GetMessage(roomID, messageID string) (*Message, error) {

	var message Message
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms/" + roomID + "/chatMessages/" + messageID)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &message)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return &message, nil
}

// SendMessage sends a message to a room
func (gitter *Gitter) SendMessage(roomID, text string) error {

	message := Message{Text: text}
	body, _ := json.Marshal(message)
	_, err := gitter.post(gitter.config.apiBaseURL+"rooms/"+roomID+"/chatMessages", body)
	if err != nil {
		gitter.log(err)
		return err
	}

	return nil
}

// JoinRoom joins a room
func (gitter *Gitter) JoinRoom(roomID, userID string) (*Room, error) {

	message := Room{ID: roomID}
	body, _ := json.Marshal(message)
	response, err := gitter.post(gitter.config.apiBaseURL+"user/"+userID+"/rooms", body)

	if err != nil {
		gitter.log(err)
		return nil, err
	}

	var room Room
	err = json.Unmarshal(response, &room)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return &room, nil
}

// LeaveRoom removes a user from the room
func (gitter *Gitter) LeaveRoom(roomID, userID string) error {

	_, err := gitter.delete(gitter.config.apiBaseURL + "rooms/" + roomID + "/users/" + userID)
	if err != nil {
		gitter.log(err)
		return err
	}

	return nil
}

// SetDebug traces errors if it's set to true.
func (gitter *Gitter) SetDebug(debug bool, logWriter io.Writer) {
	gitter.debug = debug
	gitter.logWriter = logWriter
}

// Pagination params
type Pagination struct {

	// Skip n messages
	Skip int

	// Get messages before beforeId
	BeforeID string

	// Get messages after afterId
	AfterID string

	// Maximum number of messages to return
	Limit int

	// Search query
	Query string
}

func (messageParams *Pagination) encode() string {
	values := url.Values{}

	if messageParams.AfterID != "" {
		values.Add("afterId", messageParams.AfterID)
	}

	if messageParams.BeforeID != "" {
		values.Add("beforeId", messageParams.BeforeID)
	}

	if messageParams.Skip > 0 {
		values.Add("skip", strconv.Itoa(messageParams.Skip))
	}

	if messageParams.Limit > 0 {
		values.Add("limit", strconv.Itoa(messageParams.Limit))
	}

	return values.Encode()
}

func (gitter *Gitter) getResponse(url string, stream *Stream) (*http.Response, error) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer "+gitter.config.token)
	if stream != nil {
		stream.streamConnection.request = r
	}
	response, err := gitter.config.client.Do(r)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	return response, nil
}

func (gitter *Gitter) get(url string) ([]byte, error) {
	resp, err := gitter.getResponse(url, nil)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)}
		gitter.log(err)
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return body, nil
}

func (gitter *Gitter) post(url string, body []byte) ([]byte, error) {
	r, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer "+gitter.config.token)

	resp, err := gitter.config.client.Do(r)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)}
		gitter.log(err)
		return nil, err
	}

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return result, nil
}

func (gitter *Gitter) delete(url string) ([]byte, error) {
	r, err := http.NewRequest("delete", url, nil)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer "+gitter.config.token)

	resp, err := gitter.config.client.Do(r)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)}
		gitter.log(err)
		return nil, err
	}

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return result, nil
}

func (gitter *Gitter) log(a interface{}) {
	if gitter.debug {
		log.Println(a)
		if gitter.logWriter != nil {
			timestamp := time.Now().Format(time.RFC3339)
			msg := fmt.Sprintf("%v: %v", timestamp, a)
			fmt.Fprintln(gitter.logWriter, msg)
		}
	}
}

// APIError holds data of errors returned from the API.
type APIError struct {
	What string
}

func (e APIError) Error() string {
	return fmt.Sprintf("%v", e.What)
}
<commit_msg>Add GetUsersInRoom<commit_after>// Package gitter is a Go client library for the Gitter API.
//
// Author: sromku
package gitter

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/mreiferson/go-httpclient"
)

var (
	apiBaseURL    = "https://api.gitter.im/v1/"
	streamBaseURL = "https://stream.gitter.im/v1/"
	fayeBaseURL   = "https://ws.gitter.im/faye"
)

type Gitter struct {
	config struct {
		apiBaseURL    string
		streamBaseURL string
		token         string
		client        *http.Client
	}
	debug     bool
	logWriter io.Writer
}

// New initializes the Gitter API client
//
// For example:
//  api := gitter.New("YOUR_ACCESS_TOKEN")
func New(token string) *Gitter {

	transport := &httpclient.Transport{
		ConnectTimeout:   5 * time.Second,
		ReadWriteTimeout: 40 * time.Second,
	}
	defer transport.Close()

	s := &Gitter{}
	s.config.apiBaseURL = apiBaseURL
	s.config.streamBaseURL = streamBaseURL
	s.config.token = token
	s.config.client = &http.Client{
		Transport: transport,
	}
	return s
}

// SetClient sets a custom http client. Can be useful in App Engine case.
func (gitter *Gitter) SetClient(client *http.Client) {
	gitter.config.client = client
}

// GetUser returns the current user
func (gitter *Gitter) GetUser() (*User, error) {

	var users []User
	response, err := gitter.get(gitter.config.apiBaseURL + "user")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &users)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	if len(users) > 0 {
		return &users[0], nil
	}

	err = APIError{What: "Failed to retrieve current user"}
	gitter.log(err)
	return nil, err
}

// GetUserRooms returns a list of Rooms the user is part of
func (gitter *Gitter) GetUserRooms(userID string) ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(gitter.config.apiBaseURL + "user/" + userID + "/rooms")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return rooms, nil
}

// GetRooms returns a list of rooms the current user is in
func (gitter *Gitter) GetRooms() ([]Room, error) {

	var rooms []Room
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &rooms)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return rooms, nil
}

// GetUsersInRoom returns the users in the room with the passed id
func (gitter *Gitter) GetUsersInRoom(roomID string) ([]User, error) {
	var users []User
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms/" + roomID + "/users")
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &users)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	return users, nil
}

// GetRoom returns a room with the passed id
func (gitter *Gitter) GetRoom(roomID string) (*Room, error) {

	var room Room
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms/" + roomID)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &room)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return &room, nil
}

// GetMessages returns a list of messages in a room.
// Pagination is optional. You can pass nil or specific pagination params.
func (gitter *Gitter) GetMessages(roomID string, params *Pagination) ([]Message, error) {

	var messages []Message
	url := gitter.config.apiBaseURL + "rooms/" + roomID + "/chatMessages"
	if params != nil {
		url += "?" + params.encode()
	}
	response, err := gitter.get(url)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &messages)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return messages, nil
}

// GetMessage returns a message in a room.
func (gitter *Gitter) GetMessage(roomID, messageID string) (*Message, error) {

	var message Message
	response, err := gitter.get(gitter.config.apiBaseURL + "rooms/" + roomID + "/chatMessages/" + messageID)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	err = json.Unmarshal(response, &message)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return &message, nil
}

// SendMessage sends a message to a room
func (gitter *Gitter) SendMessage(roomID, text string) error {

	message := Message{Text: text}
	body, _ := json.Marshal(message)
	_, err := gitter.post(gitter.config.apiBaseURL+"rooms/"+roomID+"/chatMessages", body)
	if err != nil {
		gitter.log(err)
		return err
	}

	return nil
}

// JoinRoom joins a room
func (gitter *Gitter) JoinRoom(roomID, userID string) (*Room, error) {

	message := Room{ID: roomID}
	body, _ := json.Marshal(message)
	response, err := gitter.post(gitter.config.apiBaseURL+"user/"+userID+"/rooms", body)

	if err != nil {
		gitter.log(err)
		return nil, err
	}

	var room Room
	err = json.Unmarshal(response, &room)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return &room, nil
}

// LeaveRoom removes a user from the room
func (gitter *Gitter) LeaveRoom(roomID, userID string) error {

	_, err := gitter.delete(gitter.config.apiBaseURL + "rooms/" + roomID + "/users/" + userID)
	if err != nil {
		gitter.log(err)
		return err
	}

	return nil
}

// SetDebug traces errors if it's set to true.
func (gitter *Gitter) SetDebug(debug bool, logWriter io.Writer) {
	gitter.debug = debug
	gitter.logWriter = logWriter
}

// Pagination params
type Pagination struct {

	// Skip n messages
	Skip int

	// Get messages before beforeId
	BeforeID string

	// Get messages after afterId
	AfterID string

	// Maximum number of messages to return
	Limit int

	// Search query
	Query string
}

func (messageParams *Pagination) encode() string {
	values := url.Values{}

	if messageParams.AfterID != "" {
		values.Add("afterId", messageParams.AfterID)
	}

	if messageParams.BeforeID != "" {
		values.Add("beforeId", messageParams.BeforeID)
	}

	if messageParams.Skip > 0 {
		values.Add("skip", strconv.Itoa(messageParams.Skip))
	}

	if messageParams.Limit > 0 {
		values.Add("limit", strconv.Itoa(messageParams.Limit))
	}

	return values.Encode()
}

func (gitter *Gitter) getResponse(url string, stream *Stream) (*http.Response, error) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer "+gitter.config.token)
	if stream != nil {
		stream.streamConnection.request = r
	}
	response, err := gitter.config.client.Do(r)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	return response, nil
}

func (gitter *Gitter) get(url string) ([]byte, error) {
	resp, err := gitter.getResponse(url, nil)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)}
		gitter.log(err)
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return body, nil
}

func (gitter *Gitter) post(url string, body []byte) ([]byte, error) {
	r, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer "+gitter.config.token)

	resp, err := gitter.config.client.Do(r)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)}
		gitter.log(err)
		return nil, err
	}

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return result, nil
}

func (gitter *Gitter) delete(url string) ([]byte, error) {
	r, err := http.NewRequest("delete", url, nil)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	r.Header.Set("Content-Type", "application/json")
	r.Header.Set("Accept", "application/json")
	r.Header.Set("Authorization", "Bearer "+gitter.config.token)

	resp, err := gitter.config.client.Do(r)
	if err != nil {
		gitter.log(err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = APIError{What: fmt.Sprintf("Status code: %v", resp.StatusCode)}
		gitter.log(err)
		return nil, err
	}

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		gitter.log(err)
		return nil, err
	}

	return result, nil
}

func (gitter *Gitter) log(a interface{}) {
	if gitter.debug {
		log.Println(a)
		if gitter.logWriter != nil {
			timestamp := time.Now().Format(time.RFC3339)
			msg := fmt.Sprintf("%v: %v", timestamp, a)
			fmt.Fprintln(gitter.logWriter, msg)
		}
	}
}

// APIError holds data of errors returned from the API.
type APIError struct {
	What string
}

func (e APIError) Error() string {
	return fmt.Sprintf("%v", e.What)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"

	"github.com/dustin/go-coap"
)

// Metric is the layout of the metric payload from a client.
type Metric struct {
	Fqdn    uint8
	Service uint8
	Key     uint8
	Value   string
}

// Pack converts the struct into a byte slice for sending on the wire
func (m Metric) Pack() []byte {
	return []byte(fmt.Sprintf("%v%v%v%v", m.Fqdn, m.Service, m.Key, m.Value))
}

func main() {
	m := Metric{
		Fqdn:    0x00000001,
		Service: 0x00000001,
		Key:     0x00000001,
		Value:   "Metric",
	}

	req := coap.Message{
		Type:      coap.Confirmable,
		Code:      coap.GET,
		MessageID: 1,
		Payload:   []byte("com.example.api my_super_service endpoint_name.method.status_code"),
	}

	req.SetPathString("register_key")

	c, err := coap.Dial("udp", "localhost:5683")
	if err != nil {
		log.Fatalf("Error dialing: %v", err)
	}

	rv, err := c.Send(req)
	if err != nil {
		log.Fatalf("Error sending request: %v", err)
	}

	if rv != nil {
		log.Printf("Response payload: %s", rv.Payload)
	}

	m = Metric{
		Fqdn:    uint8(rv.Payload[0]),
		Service: uint8(rv.Payload[1]),
		Key:     uint8(rv.Payload[2]),
		Value:   "T",
	}

	req = coap.Message{
		Type:      coap.Confirmable,
		Code:      coap.GET,
		MessageID: 1,
		Payload:   m.Pack(),
	}

	rv, err = c.Send(req)
	if err != nil {
		log.Fatalf("Error sending request: %v", err)
	}

	if rv != nil {
		log.Printf("Response payload: %s", rv.Payload)
	}

}
<commit_msg>Update test client<commit_after>package main

import (
	"fmt"
	"log"

	"github.com/dustin/go-coap"
)

// Metric is the layout of the metric payload from a client.
type Metric struct {
	Fqdn    uint8
	Service uint8
	Key     uint8
	Value   string
}

// Pack converts the struct into a byte slice for sending on the wire
func (m Metric) Pack() []byte {
	return []byte(fmt.Sprintf("%v%v%v%v", m.Fqdn, m.Service, m.Key, m.Value))
}

func main() {
	m := Metric{
		Fqdn:    0x00000001,
		Service: 0x00000001,
		Key:     0x00000001,
		Value:   "Metric",
	}

	req := coap.Message{
		Type:      coap.Confirmable,
		Code:      coap.GET,
		MessageID: 1,
		Payload:   []byte("com.example.api my_super_service endpoint_name.method.status_code"),
	}

	req.SetPathString("register_key")

	c, err := coap.Dial("udp", "localhost:5683")
	if err != nil {
		log.Fatalf("Error dialing: %v", err)
	}

	rv, err := c.Send(req)
	if err != nil {
		log.Fatalf("Error sending request: %v", err)
	}

	if rv != nil {
		log.Printf("Response payload: %s :: %#v", rv.Payload, rv.Payload)
	}

	m = Metric{
		Fqdn:    rv.Payload[0],
		Service: rv.Payload[1],
		Key:     rv.Payload[2],
		Value:   "T",
	}

	req = coap.Message{
		Type:      coap.Confirmable,
		Code:      coap.GET,
		MessageID: 1,
		Payload:   m.Pack(),
	}

	rv, err = c.Send(req)
	if err != nil {
		log.Fatalf("Error sending request: %v", err)
	}

	if rv != nil {
		log.Printf("Response payload: %s", rv.Payload)
	}

}
<|endoftext|>


<commit_before>package main

import (
  "os"
  "fmt"
  "net/http"
  "io/ioutil"
  "regexp"
  "html"
  "strings"
)

const debug = false
const MESSAGE_TYPE_START = 0
const MESSAGE_TYPE_END = 1
const MESSAGE_TYPE_PAYLOAD = 2

type Message struct {
  msgType int
  payload string
}

func sendClose(messages chan<- Message) {
  messages <- Message{msgType:MESSAGE_TYPE_END}
}

func processUrl(url string, depth int, maxDepth int, messages chan<- Message) {
  var resp *http.Response

  // Send close message once this function exits
  defer sendClose(messages)

  if debug { fmt.Println("Retrieving", url)}
  resp, err := http.Get(url)
  if err != nil {
    return
  }

  defer resp.Body.Close()
  if debug { fmt.Println("Reading response", url)}
  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    return
  }

  if debug { fmt.Println("Read", len(body), "bytes from", url) }

  bodyStr := string(body)
  // Process payload
  findPayload(bodyStr, url, messages)

  if (depth < maxDepth) {
    followLinks(bodyStr, depth+1, maxDepth, messages)
  }
}

func findPayload(input string, baseUrl string, messages chan<- Message) {
  parseStringRegexp := regexp.MustCompile("(?i)<img\\s([^<>]+\\s)?src=[\"']([^\"'<>\\s]+)")
  protocolRegexp := regexp.MustCompile("(?i)^([a-zA-Z]+:)(//[^/]*/?)(.*)([^/]*)$")

  protoMatch := protocolRegexp.FindStringSubmatch(baseUrl);

  tmp := parseStringRegexp.FindAllStringSubmatch(input, -1)
  if (tmp != nil) {
    for i :=0; i < len(tmp); i++ {
      img := tmp[i][2]
      img = html.UnescapeString(img)

      // Really crude
      if strings.Index(img, "://") == -1 {
        // No protocol => relative url
        if strings.Index(img, "//") == 0 {
          // absolute url sans protocol
          img = protoMatch[1] + img;
        } else if (img[0] == '/') {
          // Absolute wrt baseUrl
          img = protoMatch[1] + protoMatch[2] + img
        } else {
          // Just append away
          img = protoMatch[1] + protoMatch[2] + protoMatch[3] + img
        }
      }
      messages <- Message{msgType:MESSAGE_TYPE_PAYLOAD, payload:img}
    }
  } else {
    if debug { fmt.Println("no payload matches") }
  }
}

func followLinks(input string, depth int, maxDepth int, messages chan<- Message) {
  parseStringRegexp := regexp.MustCompile("https?://[^\"\\s]+")
  matches := parseStringRegexp.FindAllString(input, -1)
  if (matches != nil) {
    for i := 0; i < len(matches); i++ {
      messages <- Message{msgType:MESSAGE_TYPE_START}
      go processUrl(matches[i], depth, maxDepth, messages)
    }
  }

}

func main() {
  if len(os.Args) < 2 {
    fmt.Println("usage: scrape url1 [url2 url3 ..]")
    return
  }

  messages := make(chan Message, len(os.Args)-1)
  counter := 0
  running := true

  for i := 1; i < len(os.Args); i++ {
    messages <- Message{msgType:MESSAGE_TYPE_START}
    go processUrl(os.Args[i], 0, 1, messages)
  }
  for running {
    msg := <-messages
    switch {
    case msg.msgType == MESSAGE_TYPE_START:
      if debug { fmt.Println("open!") }
      counter++;
      break;
    case msg.msgType == MESSAGE_TYPE_END:
      if debug { fmt.Println("close..") }
      counter--;
      if (counter == 0) {
        if debug { fmt.Println("done") }
        running = false
      }
      break
    case msg.msgType == MESSAGE_TYPE_PAYLOAD:
      fmt.Println(msg.payload)
      break
    }
  }
}
<commit_msg>Make sendClose into an anonymous function<commit_after>package main

import (
  "os"
  "fmt"
  "net/http"
  "io/ioutil"
  "regexp"
  "html"
  "strings"
)

const debug = false
const MESSAGE_TYPE_START = 0
const MESSAGE_TYPE_END = 1
const MESSAGE_TYPE_PAYLOAD = 2

type Message struct {
  msgType int
  payload string
}

func processUrl(url string, depth int, maxDepth int, messages chan<- Message) {
  var resp *http.Response

  // Send close message once this function exits
  defer func() { messages <- Message{msgType:MESSAGE_TYPE_END} }()

  if debug { fmt.Println("Retrieving", url)}
  resp, err := http.Get(url)
  if err != nil {
    return
  }

  defer resp.Body.Close()
  if debug { fmt.Println("Reading response", url)}
  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    return
  }

  if debug { fmt.Println("Read", len(body), "bytes from", url) }

  bodyStr := string(body)
  // Process payload
  findPayload(bodyStr, url, messages)

  if (depth < maxDepth) {
    followLinks(bodyStr, depth+1, maxDepth, messages)
  }
}

func findPayload(input string, baseUrl string, messages chan<- Message) {
  parseStringRegexp := regexp.MustCompile("(?i)<img\\s([^<>]+\\s)?src=[\"']([^\"'<>\\s]+)")
  protocolRegexp := regexp.MustCompile("(?i)^([a-zA-Z]+:)(//[^/]*/?)(.*)([^/]*)$")

  protoMatch := protocolRegexp.FindStringSubmatch(baseUrl);

  tmp := parseStringRegexp.FindAllStringSubmatch(input, -1)
  if (tmp != nil) {
    for i :=0; i < len(tmp); i++ {
      img := tmp[i][2]
      img = html.UnescapeString(img)

      // Really crude
      if strings.Index(img, "://") == -1 {
        // No protocol => relative url
        if strings.Index(img, "//") == 0 {
          // absolute url sans protocol
          img = protoMatch[1] + img;
        } else if (img[0] == '/') {
          // Absolute wrt baseUrl
          img = protoMatch[1] + protoMatch[2] + img
        } else {
          // Just append away
          img = protoMatch[1] + protoMatch[2] + protoMatch[3] + img
        }
      }
      messages <- Message{msgType:MESSAGE_TYPE_PAYLOAD, payload:img}
    }
  } else {
    if debug { fmt.Println("no payload matches") }
  }
}

func followLinks(input string, depth int, maxDepth int, messages chan<- Message) {
  parseStringRegexp := regexp.MustCompile("https?://[^\"\\s]+")
  matches := parseStringRegexp.FindAllString(input, -1)
  if (matches != nil) {
    for i := 0; i < len(matches); i++ {
      messages <- Message{msgType:MESSAGE_TYPE_START}
      go processUrl(matches[i], depth, maxDepth, messages)
    }
  }

}

func main() {
  if len(os.Args) < 2 {
    fmt.Println("usage: scrape url1 [url2 url3 ..]")
    return
  }

  messages := make(chan Message, len(os.Args)-1)
  counter := 0
  running := true

  for i := 1; i < len(os.Args); i++ {
    messages <- Message{msgType:MESSAGE_TYPE_START}
    go processUrl(os.Args[i], 0, 1, messages)
  }
  for running {
    msg := <-messages
    switch {
    case msg.msgType == MESSAGE_TYPE_START:
      if debug { fmt.Println("open!") }
      counter++;
      break;
    case msg.msgType == MESSAGE_TYPE_END:
      if debug { fmt.Println("close..") }
      counter--;
      if (counter == 0) {
        if debug { fmt.Println("done") }
        running = false
      }
      break
    case msg.msgType == MESSAGE_TYPE_PAYLOAD:
      fmt.Println(msg.payload)
      break
    }
  }
}
<|endoftext|>


<commit_before>//Author: Gary Connelly
//date 22/09/2017

// inspired by https://play.golang.org/p/vhHmjhOMEo

package main

import "fmt"

func main() {

//create list of random numbers
	x := []int{
	 26, 42, 17, 10, 4, 67, 98, 31, 82, 56,
	}

}<commit_msg>creating a for loop to run through the array<commit_after>//Author: Gary Connelly
//date 22/09/2017

// inspired by https://play.golang.org/p/vhHmjhOMEo

package main

import "fmt"

func main() {

//create list of random numbers
	x := []int{
	 26, 42, 17, 10, 4, 67, 98, 31, 82, 56,
	}

	smallest, biggest := x[0], x[0]
	for _, v := range x {
		if v > biggest {
			biggest = v
		}
		if v < smallest {
			smallest = v
		}
	}
}<|endoftext|>