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

// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le race,linux,arm64

package race

// This file merely ensures that we link in runtime/cgo in race build,
// this is turn ensures that runtime uses pthread_create to create threads.
// The prebuilt race runtime lives in race_GOOS_GOARCH.syso.
// Calls to the runtime are done directly from src/runtime/race.go.

// void __race_unused_func(void);
import "C"
<commit_msg>runtime/race: correct typo s/is/in<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le race,linux,arm64

package race

// This file merely ensures that we link in runtime/cgo in race build,
// this in turn ensures that runtime uses pthread_create to create threads.
// The prebuilt race runtime lives in race_GOOS_GOARCH.syso.
// Calls to the runtime are done directly from src/runtime/race.go.

// void __race_unused_func(void);
import "C"
<|endoftext|>


<commit_before>package project

import "github.com/paulmach/orb"

// ToPlanar projects a geometry from geo -> planar
func ToPlanar(g orb.Geometry, proj *Projection) orb.Geometry {
	switch g := g.(type) {
	case orb.Point:
		return proj.ToPlanar(g)
	case orb.MultiPoint:
		return MultiPointToPlanar(g, proj)
	case orb.LineString:
		return LineStringToPlanar(g, proj)
	case orb.MultiLineString:
		return MultiLineStringToPlanar(g, proj)
	case orb.Ring:
		return RingToPlanar(g, proj)
	case orb.Polygon:
		return PolygonToPlanar(g, proj)
	case orb.MultiPolygon:
		return MultiPolygonToPlanar(g, proj)
	case orb.Collection:
		return CollectionToPlanar(g, proj)
	case orb.Bound:
		return BoundToPlanar(g, proj)
	}

	panic("geometry type not supported")
}

// ToGeo projects a geometry from planar -> geo
func ToGeo(g orb.Geometry, proj *Projection) orb.Geometry {
	switch g := g.(type) {
	case orb.Point:
		return proj.ToGeo(g)
	case orb.MultiPoint:
		return MultiPointToGeo(g, proj)
	case orb.LineString:
		return LineStringToGeo(g, proj)
	case orb.MultiLineString:
		return MultiLineStringToGeo(g, proj)
	case orb.Ring:
		return RingToGeo(g, proj)
	case orb.Polygon:
		return PolygonToGeo(g, proj)
	case orb.MultiPolygon:
		return MultiPolygonToGeo(g, proj)
	case orb.Collection:
		return CollectionToGeo(g, proj)
	case orb.Bound:
		return BoundToGeo(g, proj)
	}

	panic("geometry type not supported")
}

// MultiPointToPlanar is a helper to project an entire multi point.
func MultiPointToPlanar(mp orb.MultiPoint, proj *Projection) orb.MultiPoint {
	n := make(orb.MultiPoint, len(mp))
	for i := range mp {
		n[i] = proj.ToPlanar(mp[i])
	}

	return n
}

// MultiPointToGeo is a helper to project an entire multi point.
func MultiPointToGeo(mp orb.MultiPoint, proj *Projection) orb.MultiPoint {
	n := make(orb.MultiPoint, len(mp))
	for i := range mp {
		n[i] = proj.ToGeo(mp[i])
	}

	return n
}

// LineStringToPlanar is a helper to project an entire line string.
func LineStringToPlanar(ls orb.LineString, proj *Projection) orb.LineString {
	return orb.LineString(MultiPointToPlanar(orb.MultiPoint(ls), proj))
}

// LineStringToGeo is a helper to project an entire line string.
func LineStringToGeo(ls orb.LineString, proj *Projection) orb.LineString {
	return orb.LineString(MultiPointToGeo(orb.MultiPoint(ls), proj))
}

// MultiLineStringToPlanar is a helper to project an entire multi linestring.
func MultiLineStringToPlanar(mls orb.MultiLineString, proj *Projection) orb.MultiLineString {
	n := make(orb.MultiLineString, len(mls))
	for i := range mls {
		n[i] = LineStringToPlanar(mls[i], proj)
	}

	return n
}

// MultiLineStringToGeo is a helper to project an entire multi linestring.
func MultiLineStringToGeo(mls orb.MultiLineString, proj *Projection) orb.MultiLineString {
	n := make(orb.MultiLineString, len(mls))
	for i := range mls {
		n[i] = LineStringToGeo(mls[i], proj)
	}

	return n
}

// RingToPlanar is a helper to project an entire ring.
func RingToPlanar(r orb.Ring, proj *Projection) orb.Ring {
	return orb.Ring(LineStringToPlanar(orb.LineString(r), proj))
}

// RingToGeo is a helper to project an entire ring.
func RingToGeo(r orb.Ring, proj *Projection) orb.Ring {
	return orb.Ring(LineStringToGeo(orb.LineString(r), proj))
}

// PolygonToPlanar is a helper to project an entire polygon.
func PolygonToPlanar(p orb.Polygon, proj *Projection) orb.Polygon {
	n := make(orb.Polygon, len(p))
	for i := range p {
		n[i] = RingToPlanar(p[i], proj)
	}

	return n
}

// PolygonToGeo is a helper to project an entire line string.
func PolygonToGeo(p orb.Polygon, proj *Projection) orb.Polygon {
	n := make(orb.Polygon, len(p))
	for i := range p {
		n[i] = RingToGeo(p[i], proj)
	}

	return n
}

// MultiPolygonToPlanar is a helper to project an entire multi polygon.
func MultiPolygonToPlanar(mp orb.MultiPolygon, proj *Projection) orb.MultiPolygon {
	n := make(orb.MultiPolygon, len(mp))
	for i := range mp {
		n[i] = PolygonToPlanar(mp[i], proj)
	}

	return n
}

// MultiPolygonToGeo is a helper to project an entire multi linestring.
func MultiPolygonToGeo(mp orb.MultiPolygon, proj *Projection) orb.MultiPolygon {
	n := make(orb.MultiPolygon, len(mp))
	for i := range mp {
		n[i] = PolygonToGeo(mp[i], proj)
	}

	return n
}

// CollectionToPlanar is a helper to project a rectangle.
func CollectionToPlanar(c orb.Collection, proj *Projection) orb.Collection {
	n := make(orb.Collection, len(c))
	for i := range c {
		n[i] = ToPlanar(c[i], proj)
	}

	return n
}

// CollectionToGeo is a helper to project a rectangle.
func CollectionToGeo(c orb.Collection, proj *Projection) orb.Collection {
	n := make(orb.Collection, len(c))
	for i := range c {
		n[i] = ToGeo(c[i], proj)
	}

	return n
}

// BoundToPlanar is a helper to project a rectangle.
func BoundToPlanar(bound orb.Bound, proj *Projection) orb.Bound {
	return orb.NewBoundFromPoints(
		proj.ToPlanar(bound[0]),
		proj.ToPlanar(bound[1]),
	)
}

// BoundToGeo is a helper to project a rectangle.
func BoundToGeo(bound orb.Bound, proj *Projection) orb.Bound {
	return orb.NewBoundFromPoints(
		proj.ToGeo(bound[0]),
		proj.ToGeo(bound[1]),
	)
}
<commit_msg>project helpers no longe copy the data<commit_after>package project

import "github.com/paulmach/orb"

// ToPlanar projects a geometry from geo -> planar
func ToPlanar(g orb.Geometry, proj *Projection) orb.Geometry {
	switch g := g.(type) {
	case orb.Point:
		return proj.ToPlanar(g)
	case orb.MultiPoint:
		return MultiPointToPlanar(g, proj)
	case orb.LineString:
		return LineStringToPlanar(g, proj)
	case orb.MultiLineString:
		return MultiLineStringToPlanar(g, proj)
	case orb.Ring:
		return RingToPlanar(g, proj)
	case orb.Polygon:
		return PolygonToPlanar(g, proj)
	case orb.MultiPolygon:
		return MultiPolygonToPlanar(g, proj)
	case orb.Collection:
		return CollectionToPlanar(g, proj)
	case orb.Bound:
		return BoundToPlanar(g, proj)
	}

	panic("geometry type not supported")
}

// ToGeo projects a geometry from planar -> geo
func ToGeo(g orb.Geometry, proj *Projection) orb.Geometry {
	switch g := g.(type) {
	case orb.Point:
		return proj.ToGeo(g)
	case orb.MultiPoint:
		return MultiPointToGeo(g, proj)
	case orb.LineString:
		return LineStringToGeo(g, proj)
	case orb.MultiLineString:
		return MultiLineStringToGeo(g, proj)
	case orb.Ring:
		return RingToGeo(g, proj)
	case orb.Polygon:
		return PolygonToGeo(g, proj)
	case orb.MultiPolygon:
		return MultiPolygonToGeo(g, proj)
	case orb.Collection:
		return CollectionToGeo(g, proj)
	case orb.Bound:
		return BoundToGeo(g, proj)
	}

	panic("geometry type not supported")
}

// MultiPointToPlanar is a helper to project an entire multi point.
func MultiPointToPlanar(mp orb.MultiPoint, proj *Projection) orb.MultiPoint {
	for i := range mp {
		mp[i] = proj.ToPlanar(mp[i])
	}

	return mp
}

// MultiPointToGeo is a helper to project an entire multi point.
func MultiPointToGeo(mp orb.MultiPoint, proj *Projection) orb.MultiPoint {
	for i := range mp {
		mp[i] = proj.ToGeo(mp[i])
	}

	return mp
}

// LineStringToPlanar is a helper to project an entire line string.
func LineStringToPlanar(ls orb.LineString, proj *Projection) orb.LineString {
	return orb.LineString(MultiPointToPlanar(orb.MultiPoint(ls), proj))
}

// LineStringToGeo is a helper to project an entire line string.
func LineStringToGeo(ls orb.LineString, proj *Projection) orb.LineString {
	return orb.LineString(MultiPointToGeo(orb.MultiPoint(ls), proj))
}

// MultiLineStringToPlanar is a helper to project an entire multi linestring.
func MultiLineStringToPlanar(mls orb.MultiLineString, proj *Projection) orb.MultiLineString {
	for i := range mls {
		mls[i] = LineStringToPlanar(mls[i], proj)
	}

	return mls
}

// MultiLineStringToGeo is a helper to project an entire multi linestring.
func MultiLineStringToGeo(mls orb.MultiLineString, proj *Projection) orb.MultiLineString {
	for i := range mls {
		mls[i] = LineStringToGeo(mls[i], proj)
	}

	return mls
}

// RingToPlanar is a helper to project an entire ring.
func RingToPlanar(r orb.Ring, proj *Projection) orb.Ring {
	return orb.Ring(LineStringToPlanar(orb.LineString(r), proj))
}

// RingToGeo is a helper to project an entire ring.
func RingToGeo(r orb.Ring, proj *Projection) orb.Ring {
	return orb.Ring(LineStringToGeo(orb.LineString(r), proj))
}

// PolygonToPlanar is a helper to project an entire polygon.
func PolygonToPlanar(p orb.Polygon, proj *Projection) orb.Polygon {
	for i := range p {
		p[i] = RingToPlanar(p[i], proj)
	}

	return p
}

// PolygonToGeo is a helper to project an entire line string.
func PolygonToGeo(p orb.Polygon, proj *Projection) orb.Polygon {
	for i := range p {
		p[i] = RingToGeo(p[i], proj)
	}

	return p
}

// MultiPolygonToPlanar is a helper to project an entire multi polygon.
func MultiPolygonToPlanar(mp orb.MultiPolygon, proj *Projection) orb.MultiPolygon {
	for i := range mp {
		mp[i] = PolygonToPlanar(mp[i], proj)
	}

	return mp
}

// MultiPolygonToGeo is a helper to project an entire multi linestring.
func MultiPolygonToGeo(mp orb.MultiPolygon, proj *Projection) orb.MultiPolygon {
	for i := range mp {
		mp[i] = PolygonToGeo(mp[i], proj)
	}

	return mp
}

// CollectionToPlanar is a helper to project a rectangle.
func CollectionToPlanar(c orb.Collection, proj *Projection) orb.Collection {
	for i := range c {
		c[i] = ToPlanar(c[i], proj)
	}

	return c
}

// CollectionToGeo is a helper to project a rectangle.
func CollectionToGeo(c orb.Collection, proj *Projection) orb.Collection {
	for i := range c {
		c[i] = ToGeo(c[i], proj)
	}

	return c
}

// BoundToPlanar is a helper to project a rectangle.
func BoundToPlanar(bound orb.Bound, proj *Projection) orb.Bound {
	return orb.NewBoundFromPoints(
		proj.ToPlanar(bound[0]),
		proj.ToPlanar(bound[1]),
	)
}

// BoundToGeo is a helper to project a rectangle.
func BoundToGeo(bound orb.Bound, proj *Projection) orb.Bound {
	return orb.NewBoundFromPoints(
		proj.ToGeo(bound[0]),
		proj.ToGeo(bound[1]),
	)
}
<|endoftext|>


<commit_before>// Copyright 2017 Sevki <s@sevki.org>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package project // import "bldy.build/build/project"

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/vaughan0/go-ini"
)

var (
	file ini.File

	pp = ""
)

func init() {
	wd, _ := os.Getwd()
	pp = GetGitDir(wd)
	var err error
	if file, err = ini.LoadFile(filepath.Join(Root(), "bldy.cfg")); err == nil {
		if err != nil {
			log.Fatalf("error: %v", err)
		}
	}
}
func Root() (ProjectPath string) {
	return pp
}
func RelPPath(p string) string {
	rel, _ := filepath.Rel(Root(), p)
	return rel
}

func BuildOut() string {
	if os.Getenv("BUILD_OUT") != "" {
		return Getenv("BUILD_OUT")
	} else {
		return filepath.Join(
			Root(),
			"build_out",
		)
	}
}

func GetGitDir(p string) string {
	dirs := strings.Split(p, "/")
	for i := len(dirs) - 1; i > 0; i-- {
		try := fmt.Sprintf("/%s/.git", filepath.Join(dirs[0:i+1]...))
		if _, err := os.Lstat(try); os.IsNotExist(err) {
			continue
		} else if err != nil {
			log.Fatal(err)
		}
		pr, _ := filepath.Split(try)
		return pr
	}
	return ""
}

// Getenv returns the envinroment variable. It looks for the envinroment
// variable in the following order. It checks if the current shell session has
// an envinroment variable, checks if it's set in the OS specific section in
// the .build file, and checks it for common in the .build config file.
func Getenv(s string) string {
	if os.Getenv(s) != "" {
		return os.Getenv(s)
	} else if val, exists := file.Get(runtime.GOOS, s); exists {
		return val
	} else if val, exists := file.Get("", s); exists {
		return val
	} else {
		return ""
	}
}
<commit_msg>project: copy to root<commit_after>// Copyright 2017 Sevki <s@sevki.org>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package project // import "bldy.build/build/project"

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/vaughan0/go-ini"
)

var (
	file ini.File

	pp = ""

	copyToRoot = flag.Bool("r", false, "set root of the project as build out. should not be used with watch")
)

func init() {
	wd, _ := os.Getwd()
	pp = GetGitDir(wd)
	var err error
	if file, err = ini.LoadFile(filepath.Join(Root(), "bldy.cfg")); err == nil {
		if err != nil {
			log.Fatalf("error: %v", err)
		}
	}
}
func Root() (ProjectPath string) {
	return pp
}
func RelPPath(p string) string {
	rel, _ := filepath.Rel(Root(), p)
	return rel
}

func BuildOut() string {
	if *copyToRoot || Getenv("COPYTOROOT") == "true" {
		return Root()
	}

	if Getenv("BUILD_OUT") != "" {
		return Getenv("BUILD_OUT")
	} else {
		return filepath.Join(
			Root(),
			"build_out",
		)
	}
}

func GetGitDir(p string) string {
	dirs := strings.Split(p, "/")
	for i := len(dirs) - 1; i > 0; i-- {
		try := fmt.Sprintf("/%s/.git", filepath.Join(dirs[0:i+1]...))
		if _, err := os.Lstat(try); os.IsNotExist(err) {
			continue
		} else if err != nil {
			log.Fatal(err)
		}
		pr, _ := filepath.Split(try)
		return pr
	}
	return ""
}

// Getenv returns the envinroment variable. It looks for the envinroment
// variable in the following order. It checks if the current shell session has
// an envinroment variable, checks if it's set in the OS specific section in
// the .build file, and checks it for common in the .build config file.
func Getenv(s string) string {
	if os.Getenv(s) != "" {
		return os.Getenv(s)
	} else if val, exists := file.Get(runtime.GOOS, s); exists {
		return val
	} else if val, exists := file.Get("", s); exists {
		return val
	} else {
		return ""
	}
}
<|endoftext|>


<commit_before>package mastodon

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"
	"time"
)

type Config struct {
	Server       string
	ClientID     string
	ClientSecret string
	AccessToken  string
}

type client struct {
	http.Client
	config *Config
}

func NewClient(config *Config) *client {
	return &client{
		Client: *http.DefaultClient,
		config: config,
	}
}

func (c *client) Authenticate(username, password string) error {
	params := url.Values{}
	params.Set("client_id", c.config.ClientID)
	params.Set("client_secret", c.config.ClientSecret)
	params.Set("grant_type", "password")
	params.Set("username", username)
	params.Set("password", password)
	params.Set("scope", "read write follow")

	url, err := url.Parse(c.config.Server)
	if err != nil {
		return err
	}
	url.Path = path.Join(url.Path, "/oauth/token")

	req, err := http.NewRequest("POST", url.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return err
	}
	resp, err := c.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	res := struct {
		AccessToken string `json:"access_token"`
	}{}
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return err
	}
	c.config.AccessToken = res.AccessToken
	return nil
}

// AppConfig is a setting for registering applications.
type AppConfig struct {
	http.Client
	Server     string
	ClientName string

	// Where the user should be redirected after authorization (for no redirect, use urn:ietf:wg:oauth:2.0:oob)
	RedirectURIs string

	// This can be a space-separated list of the following items: "read", "write" and "follow".
	Scopes string

	// Optional.
	Website string
}

// Application is mastodon application.
type Application struct {
	ID           int64  `json:"id"`
	RedirectURI  string `json:"redirect_uri"`
	ClientID     string `json:"client_id"`
	ClientSecret string `json:"client_secret"`
}

// RegisterApp returns the mastodon application.
func RegisterApp(appConfig *AppConfig) (*Application, error) {
	params := url.Values{}
	params.Set("client_name", appConfig.ClientName)
	params.Set("redirect_uris", appConfig.RedirectURIs)
	params.Set("scopes", appConfig.Scopes)
	params.Set("website", appConfig.Website)

	url, err := url.Parse(appConfig.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, "/api/v1/apps")

	req, err := http.NewRequest("POST", url.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return nil, err
	}
	resp, err := appConfig.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	app := &Application{}
	err = json.NewDecoder(resp.Body).Decode(app)
	if err != nil {
		return nil, err
	}

	return app, nil
}

type Account struct {
	ID             int64     `json:"id"`
	Username       string    `json:"username"`
	Acct           string    `json:"acct"`
	DisplayName    string    `json:"display_name"`
	Locked         bool      `json:"locked"`
	CreatedAt      time.Time `json:"created_at"`
	FollowersCount int64     `json:"followers_count"`
	FollowingCount int64     `json:"following_count"`
	StatusesCount  int64     `json:"statuses_count"`
	Note           string    `json:"note"`
	URL            string    `json:"url"`
	Avatar         string    `json:"avatar"`
	AvatarStatic   string    `json:"avatar_static"`
	Header         string    `json:"header"`
	HeaderStatic   string    `json:"header_static"`
}

type Visibility int64

type Toot struct {
	Status      string  `json:"status"`
	InReplyToID int64   `json:"in_reply_to_id"`
	MediaIDs    []int64 `json:"in_reply_to_id"`
	Sensitive   bool    `json:"sensitive"`
	SpoilerText string  `json:"spoiler_text"`
	Visibility  string  `json:"visibility"`
}

type Status struct {
	ID                 int64         `json:"id"`
	CreatedAt          time.Time     `json:"created_at"`
	InReplyToID        interface{}   `json:"in_reply_to_id"`
	InReplyToAccountID interface{}   `json:"in_reply_to_account_id"`
	Sensitive          bool          `json:"sensitive"`
	SpoilerText        string        `json:"spoiler_text"`
	Visibility         string        `json:"visibility"`
	Application        interface{}   `json:"application"`
	Account            Account       `json:"account"`
	MediaAttachments   []interface{} `json:"media_attachments"`
	Mentions           []interface{} `json:"mentions"`
	Tags               []interface{} `json:"tags"`
	URI                string        `json:"uri"`
	Content            string        `json:"content"`
	URL                string        `json:"url"`
	ReblogsCount       int64         `json:"reblogs_count"`
	FavouritesCount    int64         `json:"favourites_count"`
	Reblog             interface{}   `json:"reblog"`
	Favourited         interface{}   `json:"favourited"`
	Reblogged          interface{}   `json:"reblogged"`
}

func (c *client) GetAccount(id int) (*Account, error) {
	url, err := url.Parse(c.config.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, fmt.Sprintf("/api/v1/accounts/%d", id))

	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", "Bearer "+c.config.AccessToken)
	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	account := &Account{}
	err = json.NewDecoder(resp.Body).Decode(account)
	if err != nil {
		return nil, err
	}
	return account, nil
}

func (c *client) GetTimelineHome() ([]*Status, error) {
	url, err := url.Parse(c.config.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, "/api/v1/timelines/home")

	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", "Bearer "+c.config.AccessToken)
	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var statuses []*Status
	err = json.NewDecoder(resp.Body).Decode(&statuses)
	if err != nil {
		return nil, err
	}
	return statuses, nil
}

func (c *client) PostStatus(toot *Toot) (*Status, error) {
	params := url.Values{}
	params.Set("status", toot.Status)
	if toot.InReplyToID > 0 {
		params.Set("in_reply_to_id", fmt.Sprint(toot.InReplyToID))
	}
	// TODO: media_ids, senstitive, spoiler_text, visibility
	//params.Set("visibility", "public")

	url, err := url.Parse(c.config.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, "/api/v1/statuses")

	req, err := http.NewRequest("POST", url.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", "Bearer "+c.config.AccessToken)
	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var status Status
	err = json.NewDecoder(resp.Body).Decode(&status)
	if err != nil {
		return nil, err
	}
	return &status, nil
}

type UpdateEvent struct {
	Status *Status
}

func (e *UpdateEvent) event() {}

type NotificationEvent struct {
}

func (e *NotificationEvent) event() {}

type DeleteEvent struct {
	ID int64
}

func (e *DeleteEvent) event() {}

type ErrorEvent struct {
	err error
}

func (e *ErrorEvent) Error() string { return e.err.Error() }
func (e *ErrorEvent) event()        {}

type Event interface {
	event()
}

func (c *client) StreamingPublic(ctx context.Context) (chan Event, error) {
	url, err := url.Parse(c.config.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, "/api/v1/streaming/public")

	var resp *http.Response

	q := make(chan Event, 10)
	go func() {
		defer ctx.Done()

		for {
			req, err := http.NewRequest("GET", url.String(), nil)
			if err == nil {
				req.Header.Set("Authorization", "Bearer "+c.config.AccessToken)
				resp, err = c.Do(req)
			}
			if err == nil {
				name := ""
				s := bufio.NewScanner(io.TeeReader(resp.Body, os.Stdout))
				for s.Scan() {
					line := s.Text()
					token := strings.SplitN(line, ":", 2)
					if len(token) != 2 {
						continue
					}
					switch strings.TrimSpace(token[0]) {
					case "event":
						name = strings.TrimSpace(token[1])
					case "data":
						switch name {
						case "update":
							var status Status
							json.Unmarshal([]byte(token[1]), &status)
							q <- &UpdateEvent{&status}
						case "notification":
						case "delete":
						}
					default:
					}
				}
				resp.Body.Close()
				err = ctx.Err()
				if err == nil {
					break
				}
			} else {
				q <- &ErrorEvent{err}
			}
			time.Sleep(3 * time.Second)
		}
	}()
	go func() {
		<-ctx.Done()
		if resp != nil && resp.Body != nil {
			resp.Body.Close()
		}
	}()
	return q, nil
}
<commit_msg>make API wrapper<commit_after>package mastodon

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"
	"time"
)

type Config struct {
	Server       string
	ClientID     string
	ClientSecret string
	AccessToken  string
}

type client struct {
	http.Client
	config *Config
}

func (c *client) doAPI(method string, uri string, params url.Values, res interface{}) error {
	url, err := url.Parse(c.config.Server)
	if err != nil {
		return err
	}
	url.Path = path.Join(url.Path, uri)

	var resp *http.Response
	req, err := http.NewRequest(method, url.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return err
	}
	req.Header.Set("Authorization", "Bearer "+c.config.AccessToken)
	resp, err = c.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	if res == nil {
		return nil
	}
	return json.NewDecoder(resp.Body).Decode(&res)
}

func NewClient(config *Config) *client {
	return &client{
		Client: *http.DefaultClient,
		config: config,
	}
}

func (c *client) Authenticate(username, password string) error {
	params := url.Values{}
	params.Set("client_id", c.config.ClientID)
	params.Set("client_secret", c.config.ClientSecret)
	params.Set("grant_type", "password")
	params.Set("username", username)
	params.Set("password", password)
	params.Set("scope", "read write follow")

	url, err := url.Parse(c.config.Server)
	if err != nil {
		return err
	}
	url.Path = path.Join(url.Path, "/oauth/token")

	req, err := http.NewRequest("POST", url.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return err
	}
	resp, err := c.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	res := struct {
		AccessToken string `json:"access_token"`
	}{}
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return err
	}
	c.config.AccessToken = res.AccessToken
	return nil
}

// AppConfig is a setting for registering applications.
type AppConfig struct {
	http.Client
	Server     string
	ClientName string

	// Where the user should be redirected after authorization (for no redirect, use urn:ietf:wg:oauth:2.0:oob)
	RedirectURIs string

	// This can be a space-separated list of the following items: "read", "write" and "follow".
	Scopes string

	// Optional.
	Website string
}

// Application is mastodon application.
type Application struct {
	ID           int64  `json:"id"`
	RedirectURI  string `json:"redirect_uri"`
	ClientID     string `json:"client_id"`
	ClientSecret string `json:"client_secret"`
}

// RegisterApp returns the mastodon application.
func RegisterApp(appConfig *AppConfig) (*Application, error) {
	params := url.Values{}
	params.Set("client_name", appConfig.ClientName)
	params.Set("redirect_uris", appConfig.RedirectURIs)
	params.Set("scopes", appConfig.Scopes)
	params.Set("website", appConfig.Website)

	url, err := url.Parse(appConfig.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, "/api/v1/apps")

	req, err := http.NewRequest("POST", url.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return nil, err
	}
	resp, err := appConfig.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	app := &Application{}
	err = json.NewDecoder(resp.Body).Decode(app)
	if err != nil {
		return nil, err
	}

	return app, nil
}

type Account struct {
	ID             int64     `json:"id"`
	Username       string    `json:"username"`
	Acct           string    `json:"acct"`
	DisplayName    string    `json:"display_name"`
	Locked         bool      `json:"locked"`
	CreatedAt      time.Time `json:"created_at"`
	FollowersCount int64     `json:"followers_count"`
	FollowingCount int64     `json:"following_count"`
	StatusesCount  int64     `json:"statuses_count"`
	Note           string    `json:"note"`
	URL            string    `json:"url"`
	Avatar         string    `json:"avatar"`
	AvatarStatic   string    `json:"avatar_static"`
	Header         string    `json:"header"`
	HeaderStatic   string    `json:"header_static"`
}

type Visibility int64

type Toot struct {
	Status      string  `json:"status"`
	InReplyToID int64   `json:"in_reply_to_id"`
	MediaIDs    []int64 `json:"in_reply_to_id"`
	Sensitive   bool    `json:"sensitive"`
	SpoilerText string  `json:"spoiler_text"`
	Visibility  string  `json:"visibility"`
}

type Status struct {
	ID                 int64         `json:"id"`
	CreatedAt          time.Time     `json:"created_at"`
	InReplyToID        interface{}   `json:"in_reply_to_id"`
	InReplyToAccountID interface{}   `json:"in_reply_to_account_id"`
	Sensitive          bool          `json:"sensitive"`
	SpoilerText        string        `json:"spoiler_text"`
	Visibility         string        `json:"visibility"`
	Application        interface{}   `json:"application"`
	Account            Account       `json:"account"`
	MediaAttachments   []interface{} `json:"media_attachments"`
	Mentions           []interface{} `json:"mentions"`
	Tags               []interface{} `json:"tags"`
	URI                string        `json:"uri"`
	Content            string        `json:"content"`
	URL                string        `json:"url"`
	ReblogsCount       int64         `json:"reblogs_count"`
	FavouritesCount    int64         `json:"favourites_count"`
	Reblog             interface{}   `json:"reblog"`
	Favourited         interface{}   `json:"favourited"`
	Reblogged          interface{}   `json:"reblogged"`
}

func (c *client) GetAccount(id int) (*Account, error) {
	var account Account
	err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d", id), nil, &account)
	if err != nil {
		return nil, err
	}
	return &account, nil
}

func (c *client) GetTimelineHome() ([]*Status, error) {
	var statuses []*Status
	err := c.doAPI("GET", "/api/v1/timelines/home", nil, &statuses)
	if err != nil {
		return nil, err
	}
	return statuses, nil
}

func (c *client) PostStatus(toot *Toot) (*Status, error) {
	params := url.Values{}
	params.Set("status", toot.Status)
	if toot.InReplyToID > 0 {
		params.Set("in_reply_to_id", fmt.Sprint(toot.InReplyToID))
	}
	// TODO: media_ids, senstitive, spoiler_text, visibility
	//params.Set("visibility", "public")

	var status Status
	err := c.doAPI("POST", "/api/v1/statuses", params, &status)
	if err != nil {
		return nil, err
	}
	return &status, nil
}

type UpdateEvent struct {
	Status *Status
}

func (e *UpdateEvent) event() {}

type NotificationEvent struct {
}

func (e *NotificationEvent) event() {}

type DeleteEvent struct {
	ID int64
}

func (e *DeleteEvent) event() {}

type ErrorEvent struct {
	err error
}

func (e *ErrorEvent) Error() string { return e.err.Error() }
func (e *ErrorEvent) event()        {}

type Event interface {
	event()
}

func (c *client) StreamingPublic(ctx context.Context) (chan Event, error) {
	url, err := url.Parse(c.config.Server)
	if err != nil {
		return nil, err
	}
	url.Path = path.Join(url.Path, "/api/v1/streaming/public")

	var resp *http.Response

	q := make(chan Event, 10)
	go func() {
		defer ctx.Done()

		for {
			req, err := http.NewRequest("GET", url.String(), nil)
			if err == nil {
				req.Header.Set("Authorization", "Bearer "+c.config.AccessToken)
				resp, err = c.Do(req)
			}
			if err == nil {
				name := ""
				s := bufio.NewScanner(io.TeeReader(resp.Body, os.Stdout))
				for s.Scan() {
					line := s.Text()
					token := strings.SplitN(line, ":", 2)
					if len(token) != 2 {
						continue
					}
					switch strings.TrimSpace(token[0]) {
					case "event":
						name = strings.TrimSpace(token[1])
					case "data":
						switch name {
						case "update":
							var status Status
							json.Unmarshal([]byte(token[1]), &status)
							q <- &UpdateEvent{&status}
						case "notification":
						case "delete":
						}
					default:
					}
				}
				resp.Body.Close()
				err = ctx.Err()
				if err == nil {
					break
				}
			} else {
				q <- &ErrorEvent{err}
			}
			time.Sleep(3 * time.Second)
		}
	}()
	go func() {
		<-ctx.Done()
		if resp != nil && resp.Body != nil {
			resp.Body.Close()
		}
	}()
	return q, nil
}
<|endoftext|>


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

// Package router provides interfaces that need to be satisfied in order to
// implement a new router on tsuru.
package router

import "fmt"

// Router is the basic interface of this package.
type Router interface {
	// AddBackend adds a new backend.
	AddBackend(name string) error

	// RemoveBackend removes a backend.
	RemoveBackend(name string) error

	// AddRoute adds a new route.
	AddRoute(name, address string) error

	// Remove removes a route.
	RemoveRoute(name, address string) error

	// AddCNAME adds a CNAME
	AddCNAME(cname, name, address string) error

	// RemoveCNAME removes a CNAME
	RemoveCNAME(cname, address string) error

	// Addr returns the route address.
	Addr(name string) (string, error)
}

var routers = make(map[string]Router)

// Register registers a new router.
func Register(name string, r Router) {
	routers[name] = r
}

// Get gets the named router from the registry.
func Get(name string) (Router, error) {
	r, ok := routers[name]
	if !ok {
		return nil, fmt.Errorf("Unknown router: %q.", name)
	}
	return r, nil
}
<commit_msg>router: remove some captain obvious comments<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package router provides interfaces that need to be satisfied in order to
// implement a new router on tsuru.
package router

import "fmt"

// Router is the basic interface of this package. It provides methods for
// managing backends and routes. Each backend can have multiple routes.
type Router interface {
	AddBackend(name string) error
	RemoveBackend(name string) error
	AddRoute(name, address string) error
	RemoveRoute(name, address string) error
	AddCNAME(cname, name, address string) error
	RemoveCNAME(cname, address string) error
	Addr(name string) (string, error)
}

var routers = make(map[string]Router)

// Register registers a new router.
func Register(name string, r Router) {
	routers[name] = r
}

// Get gets the named router from the registry.
func Get(name string) (Router, error) {
	r, ok := routers[name]
	if !ok {
		return nil, fmt.Errorf("Unknown router: %q.", name)
	}
	return r, nil
}
<|endoftext|>


<commit_before>package steps_test

import (
	"errors"
	"sync"
	"time"

	. "github.com/cloudfoundry-incubator/executor/depot/steps"
	"github.com/cloudfoundry-incubator/executor/depot/steps/fakes"
	"github.com/cloudfoundry/gunk/timeprovider/faketimeprovider"
	"github.com/pivotal-golang/lager/lagertest"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("MonitorStep", func() {
	var (
		check          *fakes.FakeStep
		receivedEvents <-chan HealthEvent
		timeProvider   *faketimeprovider.FakeTimeProvider

		startTimeout      time.Duration
		healthyInterval   time.Duration
		unhealthyInterval time.Duration

		step   Step
		logger *lagertest.TestLogger
	)

	BeforeEach(func() {
		startTimeout = 0
		healthyInterval = 1 * time.Second
		unhealthyInterval = 500 * time.Millisecond

		timeProvider = faketimeprovider.New(time.Now())
		check = new(fakes.FakeStep)
		logger = lagertest.NewTestLogger("test")
	})

	JustBeforeEach(func() {
		events := make(chan HealthEvent, 1000)
		receivedEvents = events

		step = NewMonitor(
			check,
			events,
			logger,
			timeProvider,
			startTimeout,
			healthyInterval,
			unhealthyInterval,
		)
	})

	Describe("Perform", func() {
		var (
			checkResults chan<- error

			performErr     chan error
			donePerforming *sync.WaitGroup
		)

		expectCheckAfterInterval := func(d time.Duration) {
			previousCheckCount := check.PerformCallCount()

			timeProvider.Increment(d - 1*time.Microsecond)
			Consistently(check.PerformCallCount, 0.05).Should(Equal(previousCheckCount))

			timeProvider.Increment(d)
			Eventually(check.PerformCallCount).Should(Equal(previousCheckCount + 1))
		}

		BeforeEach(func() {
			results := make(chan error, 10)
			checkResults = results

			var currentResult error
			check.PerformStub = func() error {
				select {
				case currentResult = <-results:
				default:
				}

				return currentResult
			}
		})

		JustBeforeEach(func() {
			performErr = make(chan error, 1)
			donePerforming = new(sync.WaitGroup)

			donePerforming.Add(1)
			go func() {
				defer donePerforming.Done()
				performErr <- step.Perform()
			}()
		})

		AfterEach(func() {
			step.Cancel()
			donePerforming.Wait()
		})

		Context("when the check succeeds", func() {
			BeforeEach(func() {
				checkResults <- nil
			})

			Context("and the unhealthy interval passes", func() {
				JustBeforeEach(func() {
					expectCheckAfterInterval(unhealthyInterval)
				})

				It("emits a healthy event", func() {
					Eventually(receivedEvents).Should(Receive(Equal(Healthy)))
				})

				It("logs the step", func() {
					Ω(logger.TestSink.LogMessages()).Should(ConsistOf([]string{
						"test.monitor-step.transitioned-to-healthy",
					}))
				})

				Context("and the healthy interval passes", func() {
					JustBeforeEach(func() {
						Eventually(receivedEvents).Should(Receive(Equal(Healthy)))
						expectCheckAfterInterval(healthyInterval)
					})

					It("does not emit another healthy event", func() {
						Consistently(receivedEvents).ShouldNot(Receive())
					})
				})

				Context("and the check begins to fail", func() {
					disaster := errors.New("oh no!")

					BeforeEach(func() {
						checkResults <- disaster
					})

					Context("and the healthy interval passes", func() {
						JustBeforeEach(func() {
							expectCheckAfterInterval(healthyInterval)
						})

						It("emits an unhealthy event", func() {
							Eventually(receivedEvents).Should(Receive(Equal(Unhealthy)))
						})

						It("logs the step", func() {
							Ω(logger.TestSink.LogMessages()).Should(ConsistOf([]string{
								"test.monitor-step.transitioned-to-healthy",
								"test.monitor-step.transitioned-to-unhealthy",
							}))
						})

						It("completes with failure", func() {
							Eventually(performErr).Should(Receive(Equal(disaster)))
						})
					})
				})
			})
		})

		Context("when the check is failing immediately", func() {
			BeforeEach(func() {
				checkResults <- errors.New("not up yet!")
			})

			Context("and the start timeout is exceeded", func() {
				BeforeEach(func() {
					startTimeout = 50 * time.Millisecond
					unhealthyInterval = 30 * time.Millisecond
				})

				It("completes with failure", func() {
					expectCheckAfterInterval(unhealthyInterval)
					Consistently(performErr).ShouldNot(Receive())
					expectCheckAfterInterval(unhealthyInterval)
					Eventually(performErr).Should(Receive(MatchError("not up yet!")))
				})

				It("logs the step", func() {
					timeProvider.Increment(startTimeout + time.Millisecond)
					Eventually(logger.TestSink.LogMessages).Should(ConsistOf([]string{
						"test.monitor-step.timed-out-before-healthy",
					}))
				})
			})

			Context("and the unhealthy interval passes", func() {
				JustBeforeEach(func() {
					expectCheckAfterInterval(unhealthyInterval)
				})

				It("does not emit an unhealthy event", func() {
					Consistently(receivedEvents).ShouldNot(Receive())
				})

				It("does not exit", func() {
					Consistently(performErr).ShouldNot(Receive())
				})

				Context("and the unhealthy interval passes again", func() {
					JustBeforeEach(func() {
						expectCheckAfterInterval(unhealthyInterval)
					})

					It("does not emit an unhealthy event", func() {
						Consistently(receivedEvents).ShouldNot(Receive())
					})

					It("does not exit", func() {
						Consistently(performErr).ShouldNot(Receive())
					})
				})
			})
		})
	})

	Describe("Cancel", func() {
		It("interrupts the monitoring", func() {
			performResult := make(chan error)
			s := step
			go func() { performResult <- s.Perform() }()
			s.Cancel()
			Eventually(performResult).Should(Receive())
			Ω(logger.TestSink.LogMessages()).Should(ConsistOf([]string{
				"test.monitor-step.cancelling",
			}))
		})
	})
})
<commit_msg>Fix timing in monitor step test<commit_after>package steps_test

import (
	"errors"
	"sync"
	"time"

	. "github.com/cloudfoundry-incubator/executor/depot/steps"
	"github.com/cloudfoundry-incubator/executor/depot/steps/fakes"
	"github.com/cloudfoundry/gunk/timeprovider/faketimeprovider"
	"github.com/pivotal-golang/lager/lagertest"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("MonitorStep", func() {
	var (
		check          *fakes.FakeStep
		receivedEvents <-chan HealthEvent
		timeProvider   *faketimeprovider.FakeTimeProvider

		startTimeout      time.Duration
		healthyInterval   time.Duration
		unhealthyInterval time.Duration

		step   Step
		logger *lagertest.TestLogger
	)

	BeforeEach(func() {
		startTimeout = 0
		healthyInterval = 1 * time.Second
		unhealthyInterval = 500 * time.Millisecond

		timeProvider = faketimeprovider.New(time.Now())
		check = new(fakes.FakeStep)
		logger = lagertest.NewTestLogger("test")
	})

	JustBeforeEach(func() {
		events := make(chan HealthEvent, 1000)
		receivedEvents = events

		step = NewMonitor(
			check,
			events,
			logger,
			timeProvider,
			startTimeout,
			healthyInterval,
			unhealthyInterval,
		)
	})

	Describe("Perform", func() {
		var (
			checkResults chan<- error

			performErr     chan error
			donePerforming *sync.WaitGroup
		)

		expectCheckAfterInterval := func(d time.Duration) {
			previousCheckCount := check.PerformCallCount()

			timeProvider.Increment(d - 1*time.Microsecond)
			Consistently(check.PerformCallCount, 0.05).Should(Equal(previousCheckCount))

			timeProvider.Increment(d)
			Eventually(check.PerformCallCount).Should(Equal(previousCheckCount + 1))
		}

		BeforeEach(func() {
			results := make(chan error, 10)
			checkResults = results

			var currentResult error
			check.PerformStub = func() error {
				select {
				case currentResult = <-results:
				default:
				}

				return currentResult
			}
		})

		JustBeforeEach(func() {
			performErr = make(chan error, 1)
			donePerforming = new(sync.WaitGroup)

			donePerforming.Add(1)
			go func() {
				defer donePerforming.Done()
				performErr <- step.Perform()
			}()
		})

		AfterEach(func() {
			step.Cancel()
			donePerforming.Wait()
		})

		Context("when the check succeeds", func() {
			BeforeEach(func() {
				checkResults <- nil
			})

			Context("and the unhealthy interval passes", func() {
				JustBeforeEach(func() {
					expectCheckAfterInterval(unhealthyInterval)
				})

				It("emits a healthy event", func() {
					Eventually(receivedEvents).Should(Receive(Equal(Healthy)))
				})

				It("logs the step", func() {
					Ω(logger.TestSink.LogMessages()).Should(ConsistOf([]string{
						"test.monitor-step.transitioned-to-healthy",
					}))
				})

				Context("and the healthy interval passes", func() {
					JustBeforeEach(func() {
						Eventually(receivedEvents).Should(Receive(Equal(Healthy)))
						expectCheckAfterInterval(healthyInterval)
					})

					It("does not emit another healthy event", func() {
						Consistently(receivedEvents).ShouldNot(Receive())
					})
				})

				Context("and the check begins to fail", func() {
					disaster := errors.New("oh no!")

					BeforeEach(func() {
						checkResults <- disaster
					})

					Context("and the healthy interval passes", func() {
						JustBeforeEach(func() {
							expectCheckAfterInterval(healthyInterval)
						})

						It("emits an unhealthy event", func() {
							Eventually(receivedEvents).Should(Receive(Equal(Unhealthy)))
						})

						It("logs the step", func() {
							Ω(logger.TestSink.LogMessages()).Should(ConsistOf([]string{
								"test.monitor-step.transitioned-to-healthy",
								"test.monitor-step.transitioned-to-unhealthy",
							}))
						})

						It("completes with failure", func() {
							Eventually(performErr).Should(Receive(Equal(disaster)))
						})
					})
				})
			})
		})

		Context("when the check is failing immediately", func() {
			BeforeEach(func() {
				checkResults <- errors.New("not up yet!")
			})

			Context("and the start timeout is exceeded", func() {
				BeforeEach(func() {
					startTimeout = 50 * time.Millisecond
					unhealthyInterval = 30 * time.Millisecond
				})

				It("completes with failure", func() {
					expectCheckAfterInterval(unhealthyInterval)
					Consistently(performErr).ShouldNot(Receive())
					expectCheckAfterInterval(unhealthyInterval)
					Eventually(performErr).Should(Receive(MatchError("not up yet!")))
				})

				It("logs the step", func() {
					expectCheckAfterInterval(unhealthyInterval)
					expectCheckAfterInterval(unhealthyInterval)
					Eventually(logger.TestSink.LogMessages).Should(ConsistOf([]string{
						"test.monitor-step.timed-out-before-healthy",
					}))
				})
			})

			Context("and the unhealthy interval passes", func() {
				JustBeforeEach(func() {
					expectCheckAfterInterval(unhealthyInterval)
				})

				It("does not emit an unhealthy event", func() {
					Consistently(receivedEvents).ShouldNot(Receive())
				})

				It("does not exit", func() {
					Consistently(performErr).ShouldNot(Receive())
				})

				Context("and the unhealthy interval passes again", func() {
					JustBeforeEach(func() {
						expectCheckAfterInterval(unhealthyInterval)
					})

					It("does not emit an unhealthy event", func() {
						Consistently(receivedEvents).ShouldNot(Receive())
					})

					It("does not exit", func() {
						Consistently(performErr).ShouldNot(Receive())
					})
				})
			})
		})
	})

	Describe("Cancel", func() {
		It("interrupts the monitoring", func() {
			performResult := make(chan error)
			s := step
			go func() { performResult <- s.Perform() }()
			s.Cancel()
			Eventually(performResult).Should(Receive())
			Ω(logger.TestSink.LogMessages()).Should(ConsistOf([]string{
				"test.monitor-step.cancelling",
			}))
		})
	})
})
<|endoftext|>


<commit_before>// +build tools

/*
Copyright 2020 The Knative Authors

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

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

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

package tools

import (
	_ "knative.dev/hack"
	_ "knative.dev/pkg/hack"
)
<commit_msg>Format go code (#188)<commit_after>//go:build tools
// +build tools

/*
Copyright 2020 The Knative Authors

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

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

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

package tools

import (
	_ "knative.dev/hack"
	_ "knative.dev/pkg/hack"
)
<|endoftext|>


<commit_before>package hashvalues

import (
	"hash"
	"net/url"
)

type HashValues struct {
	Values   *url.Values
	hashfunc hash.Hash
	hashkey  []byte
}

func NewHashValues(hashkey []byte, hashfunc hash.Hash) *HashValues {
	return &HashValues{
		Values:   &url.Values{},
		hashfunc: hashfunc,
		hashkey:  hashkey,
	}
}
<commit_msg>Add Get, Set, Del, Add.<commit_after>package hashvalues

import (
	"hash"
	"net/url"
)

type HashValues struct {
	Values   *url.Values
	hashfunc hash.Hash
	hashkey  []byte
}

func NewHashValues(hashkey []byte, hashfunc hash.Hash) *HashValues {
	return &HashValues{
		Values:   &url.Values{},
		hashfunc: hashfunc,
		hashkey:  hashkey,
	}
}

func (h *HashValues) Set(key, value string) {
	h.Values.Set(key, value)
}

func (h *HashValues) Add(key, value string) {
	h.Values.Add(key, value)
}

func (h *HashValues) Del(key string) {
	h.Values.Del(key)
}

func (h *HashValues) Get(key string) string {
	return h.Values.Get(key)
}
<|endoftext|>


<commit_before>package notebook

// Notebook is an interface which represents
// a collection of notes
type Notebook interface {
    // List returns the list of notes holding in the notebook
    List() Notes

    // Get returns a note from the notebook according to its name
    Get(string) (*Note, error)

    // Set adds or updates a note in the notebook
    Set(string, *Note) error

    // Delete deletes a note from the notebook according to its name
    Delete(string) error
}
<commit_msg>fix(notebook): fixes a comment in the Notebook interface<commit_after>package notebook

// Notebook is an interface which represents
// a collection of notes
type Notebook interface {
    // List returns a list of notes holding in the notebook
    List() Notes

    // Get returns a note from the notebook according to its name
    Get(string) (*Note, error)

    // Set adds or updates a note in the notebook
    Set(string, *Note) error

    // Delete deletes a note from the notebook according to its name
    Delete(string) error
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v3rpc

import (
	"io"

	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
	"github.com/coreos/etcd/storage"
)

type watchServer struct {
	watchable storage.Watchable
}

func NewWatchServer(w storage.Watchable) pb.WatchServer {
	return &watchServer{w}
}

func (ws *watchServer) Watch(stream pb.Watch_WatchServer) error {
	closec := make(chan struct{})
	defer close(closec)

	watcher := ws.watchable.NewWatcher()
	defer watcher.Close()

	go sendLoop(stream, watcher, closec)

	for {
		req, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}

		var prefix bool
		toWatch := req.Key
		if len(req.Key) == 0 {
			toWatch = req.Prefix
			prefix = true
		}
		// TODO: support cancellation
		watcher.Watch(toWatch, prefix, req.StartRevision)
	}
}

func sendLoop(stream pb.Watch_WatchServer, watcher storage.Watcher, closec chan struct{}) {
	for {
		select {
		case e, ok := <-watcher.Chan():
			if !ok {
				return
			}
			err := stream.Send(&pb.WatchResponse{Event: &e})
			storage.ReportEventReceived()
			if err != nil {
				return
			}
		case <-closec:
			// drain the chan to clean up pending events
			for {
				_, ok := <-watcher.Chan()
				if !ok {
					return
				}
				storage.ReportEventReceived()
			}
			return
		}
	}
}
<commit_msg>v3rpc: Tiny clean up<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v3rpc

import (
	"io"

	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
	"github.com/coreos/etcd/storage"
)

type watchServer struct {
	watchable storage.Watchable
}

func NewWatchServer(w storage.Watchable) pb.WatchServer {
	return &watchServer{w}
}

func (ws *watchServer) Watch(stream pb.Watch_WatchServer) error {
	closec := make(chan struct{})
	defer close(closec)

	watcher := ws.watchable.NewWatcher()
	defer watcher.Close()

	go sendLoop(stream, watcher, closec)

	for {
		req, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}

		var prefix bool
		toWatch := req.Key
		if len(req.Key) == 0 {
			toWatch = req.Prefix
			prefix = true
		}
		// TODO: support cancellation
		watcher.Watch(toWatch, prefix, req.StartRevision)
	}
}

func sendLoop(stream pb.Watch_WatchServer, watcher storage.Watcher, closec chan struct{}) {
	for {
		select {
		case e, ok := <-watcher.Chan():
			if !ok {
				return
			}
			err := stream.Send(&pb.WatchResponse{Event: &e})
			storage.ReportEventReceived()
			if err != nil {
				return
			}
		case <-closec:
			// drain the chan to clean up pending events
			for {
				_, ok := <-watcher.Chan()
				if !ok {
					return
				}
				storage.ReportEventReceived()
			}
		}
	}
}
<|endoftext|>


<commit_before>package urknall

import (
	"crypto/sha256"
	"fmt"
	"github.com/dynport/gossh"
	"github.com/dynport/urknall/cmd"
	"path"
	"strings"
	"time"
)

type ProvisionOptions struct {
	DryRun bool
}

type sshClient struct {
	client           *gossh.Client
	host             *Host
	provisionOptions ProvisionOptions
}

func newSSHClient(host *Host, opts *ProvisionOptions) (client *sshClient) {
	if opts == nil {
		opts = &ProvisionOptions{}
	}
	c := gossh.New(host.IP, host.user())
	if host.Password != "" {
		c.SetPassword(host.Password)
	}
	return &sshClient{host: host, client: c, provisionOptions: *opts}
}

func (sc *sshClient) provision() (e error) {
	if e = sc.host.precompileRunlists(); e != nil {
		return e
	}

	return provisionRunlists(sc.host.runlists(), sc.provisionRunlist)
}

func (sc *sshClient) provisionRunlist(rl *Runlist) (e error) {
	tasks := sc.buildTasksForRunlist(rl)

	checksumDir := fmt.Sprintf("/var/cache/urknall/%s", rl.name)

	checksumHash, e := sc.buildChecksumHash(checksumDir)
	if e != nil {
		return fmt.Errorf("failed to build checksum hash: %s", e.Error())
	}

	for i := range tasks {
		task := tasks[i]
		logMsg := task.command.Logging()
		m := &Message{key: MessageRunlistsProvisionTask, task: task, message: logMsg, host: sc.host, runlist: rl}
		if _, found := checksumHash[task.checksum]; found { // Task is cached.
			m.execStatus = statusCached
			m.publish("finished")
			delete(checksumHash, task.checksum) // Delete checksums of cached tasks from hash.
			continue
		}

		if len(checksumHash) > 0 { // All remaining checksums are invalid, as something changed.
			if e = sc.cleanUpRemainingCachedEntries(checksumDir, checksumHash); e != nil {
				return e
			}
			checksumHash = make(map[string]struct{})
		}
		m.execStatus = statusExecStart
		m.publish("started")
		e = sc.runTask(task, checksumDir)
		m.error_ = e
		m.execStatus = statusExecFinished
		m.publish("finished")
		if e != nil {
			return e
		}
	}

	return nil
}

func newDebugWriter(host *Host, task *taskData) func(i ...interface{}) {
	started := time.Now()
	return func(i ...interface{}) {
		parts := strings.SplitN(fmt.Sprint(i...), "\t", 3)
		if len(parts) == 3 {
			stream, line := parts[1], parts[2]
			var runlist *Runlist = nil
			if task != nil {
				runlist = task.runlist
			}
			m := &Message{key: "task.io", host: host, stream: stream, task: task, line: line, runlist: runlist, totalRuntime: time.Now().Sub(started)}
			m.publish(stream)
		}
	}
}

func (sc *sshClient) runTask(task *taskData, checksumDir string) (e error) {
	if sc.provisionOptions.DryRun {
		return nil
	}

	stderr := fmt.Sprintf(">(while read line; do echo \"$(date --iso-8601=ns)\tstderr\t$line\"; done | tee /tmp/%s.%s.stderr)", sc.host.user(), task.checksum)
	stdout := fmt.Sprintf(">(while read line; do echo \"$(date --iso-8601=ns)\tstdout\t$line\"; done | tee /tmp/%s.%s.stdout)", sc.host.user(), task.checksum)

	sc.client.DebugWriter = newDebugWriter(sc.host, task)

	sCmd := fmt.Sprintf("bash <<EOF_RUNTASK 2> %s 1> %s\n%s\nEOF_RUNTASK\n", stderr, stdout, task.command.Shell())
	if sc.host.isSudoRequired() {
		sCmd = fmt.Sprintf("sudo %s", sCmd)
	}
	rsp, e := sc.client.Execute(sCmd)

	// Write the checksum file (containing information on the command run).
	sc.writeChecksumFile(checksumDir, task.checksum, e != nil, task.command.Logging(), rsp)

	if e != nil {
		return fmt.Errorf("%s (see %s/%s.failed for more information)", e.Error(), checksumDir, task.checksum)
	}
	return nil
}

func (sc *sshClient) executeCommand(cmdRaw string) *gossh.Result {
	cmdRaw = fmt.Sprintf("bash <<EOF_ZWO_SUDO\n%s\nEOF_ZWO_SUDO\n", cmdRaw)
	if sc.host.isSudoRequired() {
		cmdRaw = "sudo " + cmdRaw
	}
	c := &cmd.ShellCommand{Command: cmdRaw}
	result, e := sc.client.Execute(c.Shell())
	if e != nil {
		stderr := ""
		if result != nil {
			stderr = strings.TrimSpace(result.Stderr())
		}
		panic(fmt.Errorf("internal error: %s (%s)", e.Error(), stderr))
	}
	return result
}

func (sc *sshClient) buildChecksumHash(checksumDir string) (checksumMap map[string]struct{}, e error) {
	// Make sure the directory exists.
	sc.executeCommand(fmt.Sprintf("mkdir -p %s", checksumDir))

	checksums := []string{}
	// The subshell for the if state requires the escaping of the '$' so that the variable is only expanded in the
	// subshell.
	rsp := sc.executeCommand(fmt.Sprintf(`for f in "%s"/*.done; do if [[ -f "\$f" ]]; then echo -n "\$f "; fi; done`, checksumDir))
	for _, checksumFile := range strings.Fields(rsp.Stdout()) {
		checksum := strings.TrimSuffix(path.Base(checksumFile), ".done")
		checksums = append(checksums, checksum)
	}

	checksumMap = make(map[string]struct{})
	for i := range checksums {
		if len(checksums[i]) != 64 {
			return nil, fmt.Errorf("invalid checksum '%s' found in '%s'", checksums[i], checksumDir)
		}
		checksumMap[checksums[i]] = struct{}{}
	}
	return checksumMap, nil
}

func (sc *sshClient) cleanUpRemainingCachedEntries(checksumDir string, checksumHash map[string]struct{}) (e error) {
	invalidCacheEntries := make([]string, 0, len(checksumHash))
	for k, _ := range checksumHash {
		invalidCacheEntries = append(invalidCacheEntries, fmt.Sprintf("%s.done", k))
	}
	if sc.provisionOptions.DryRun {
		(&Message{key: MessageCleanupCacheEntries, invalidatedCachentries: invalidCacheEntries, host: sc.host}).publish(".dryrun")
	} else {
		cmd := fmt.Sprintf("cd %s && rm -f *.failed %s", checksumDir, strings.Join(invalidCacheEntries, " "))
		m := &Message{command: cmd, host: sc.host, key: MessageUrknallInternal}
		m.publish("started")
		result := sc.executeCommand(cmd)
		m.sshResult = result
		m.publish("finished")
	}
	return nil
}

func (sc *sshClient) writeChecksumFile(checksumDir, checksum string, failed bool, logMsg string, response *gossh.Result) {
	tmpChecksumFiles := "/tmp/" + sc.host.user() + "." + checksum + ".std*"
	checksumFile := checksumDir + "/" + checksum
	if failed {
		checksumFile += ".failed"
	} else {
		checksumFile += ".done"
	}

	// Whoa, super hacky stuff to get the command to the checksum file. The command might contain a lot of stuff, like
	// apostrophes and the like, that would totally nuke a quoted string. Though there is a here doc.
	c := []string{
		fmt.Sprintf(`cat %s | sort >> %s`, tmpChecksumFiles, checksumFile),
		fmt.Sprintf(`rm -f %s`, tmpChecksumFiles),
	}
	sc.executeCommand(fmt.Sprintf("cat <<EOF_COMMAND > %s && %s\n%s\nEOF_COMMAND\n", checksumFile, strings.Join(c, " && "), logMsg))
}

type taskData struct {
	command  cmd.Command // The command to be executed.
	checksum string      // The checksum of the command.
	runlist  *Runlist
}

func (data *taskData) Command() cmd.Command {
	return data.command
}

func (sc *sshClient) buildTasksForRunlist(rl *Runlist) (tasks []*taskData) {
	tasks = make([]*taskData, 0, len(rl.commands))

	cmdHash := sha256.New()
	for i := range rl.commands {
		rawCmd := rl.commands[i].Shell()
		cmdHash.Write([]byte(rawCmd))

		task := &taskData{runlist: rl, command: rl.commands[i], checksum: fmt.Sprintf("%x", cmdHash.Sum(nil))}
		tasks = append(tasks, task)
	}
	return tasks
}
<commit_msg>moved checksum directory<commit_after>package urknall

import (
	"crypto/sha256"
	"fmt"
	"github.com/dynport/gossh"
	"github.com/dynport/urknall/cmd"
	"path"
	"strings"
	"time"
)

type ProvisionOptions struct {
	DryRun bool
}

type sshClient struct {
	client           *gossh.Client
	host             *Host
	provisionOptions ProvisionOptions
}

// Directory checksums are stored in.
const checksumRootDir = "/var/lib/urknall"

func newSSHClient(host *Host, opts *ProvisionOptions) (client *sshClient) {
	if opts == nil {
		opts = &ProvisionOptions{}
	}
	c := gossh.New(host.IP, host.user())
	if host.Password != "" {
		c.SetPassword(host.Password)
	}
	return &sshClient{host: host, client: c, provisionOptions: *opts}
}

func (sc *sshClient) provision() (e error) {
	if e = sc.host.precompileRunlists(); e != nil {
		return e
	}

	return provisionRunlists(sc.host.runlists(), sc.provisionRunlist)
}

func (sc *sshClient) provisionRunlist(rl *Runlist) (e error) {
	tasks := sc.buildTasksForRunlist(rl)

	checksumDir := fmt.Sprintf(checksumRootDir+"/%s", rl.name)

	checksumHash, e := sc.buildChecksumHash(checksumDir)
	if e != nil {
		return fmt.Errorf("failed to build checksum hash: %s", e.Error())
	}

	for i := range tasks {
		task := tasks[i]
		logMsg := task.command.Logging()
		m := &Message{key: MessageRunlistsProvisionTask, task: task, message: logMsg, host: sc.host, runlist: rl}
		if _, found := checksumHash[task.checksum]; found { // Task is cached.
			m.execStatus = statusCached
			m.publish("finished")
			delete(checksumHash, task.checksum) // Delete checksums of cached tasks from hash.
			continue
		}

		if len(checksumHash) > 0 { // All remaining checksums are invalid, as something changed.
			if e = sc.cleanUpRemainingCachedEntries(checksumDir, checksumHash); e != nil {
				return e
			}
			checksumHash = make(map[string]struct{})
		}
		m.execStatus = statusExecStart
		m.publish("started")
		e = sc.runTask(task, checksumDir)
		m.error_ = e
		m.execStatus = statusExecFinished
		m.publish("finished")
		if e != nil {
			return e
		}
	}

	return nil
}

func newDebugWriter(host *Host, task *taskData) func(i ...interface{}) {
	started := time.Now()
	return func(i ...interface{}) {
		parts := strings.SplitN(fmt.Sprint(i...), "\t", 3)
		if len(parts) == 3 {
			stream, line := parts[1], parts[2]
			var runlist *Runlist = nil
			if task != nil {
				runlist = task.runlist
			}
			m := &Message{key: "task.io", host: host, stream: stream, task: task, line: line, runlist: runlist, totalRuntime: time.Now().Sub(started)}
			m.publish(stream)
		}
	}
}

func (sc *sshClient) runTask(task *taskData, checksumDir string) (e error) {
	if sc.provisionOptions.DryRun {
		return nil
	}

	stderr := fmt.Sprintf(">(while read line; do echo \"$(date --iso-8601=ns)\tstderr\t$line\"; done | tee /tmp/%s.%s.stderr)", sc.host.user(), task.checksum)
	stdout := fmt.Sprintf(">(while read line; do echo \"$(date --iso-8601=ns)\tstdout\t$line\"; done | tee /tmp/%s.%s.stdout)", sc.host.user(), task.checksum)

	sc.client.DebugWriter = newDebugWriter(sc.host, task)

	sCmd := fmt.Sprintf("bash <<EOF_RUNTASK 2> %s 1> %s\n%s\nEOF_RUNTASK\n", stderr, stdout, task.command.Shell())
	if sc.host.isSudoRequired() {
		sCmd = fmt.Sprintf("sudo %s", sCmd)
	}
	rsp, e := sc.client.Execute(sCmd)

	// Write the checksum file (containing information on the command run).
	sc.writeChecksumFile(checksumDir, task.checksum, e != nil, task.command.Logging(), rsp)

	if e != nil {
		return fmt.Errorf("%s (see %s/%s.failed for more information)", e.Error(), checksumDir, task.checksum)
	}
	return nil
}

func (sc *sshClient) executeCommand(cmdRaw string) *gossh.Result {
	cmdRaw = fmt.Sprintf("bash <<EOF_ZWO_SUDO\n%s\nEOF_ZWO_SUDO\n", cmdRaw)
	if sc.host.isSudoRequired() {
		cmdRaw = "sudo " + cmdRaw
	}
	c := &cmd.ShellCommand{Command: cmdRaw}
	result, e := sc.client.Execute(c.Shell())
	if e != nil {
		stderr := ""
		if result != nil {
			stderr = strings.TrimSpace(result.Stderr())
		}
		panic(fmt.Errorf("internal error: %s (%s)", e.Error(), stderr))
	}
	return result
}

func (sc *sshClient) buildChecksumHash(checksumDir string) (checksumMap map[string]struct{}, e error) {
	// Make sure the directory exists.
	sc.executeCommand(fmt.Sprintf("mkdir -p %s", checksumDir))

	checksums := []string{}
	// The subshell for the if state requires the escaping of the '$' so that the variable is only expanded in the
	// subshell.
	rsp := sc.executeCommand(fmt.Sprintf(`for f in "%s"/*.done; do if [[ -f "\$f" ]]; then echo -n "\$f "; fi; done`, checksumDir))
	for _, checksumFile := range strings.Fields(rsp.Stdout()) {
		checksum := strings.TrimSuffix(path.Base(checksumFile), ".done")
		checksums = append(checksums, checksum)
	}

	checksumMap = make(map[string]struct{})
	for i := range checksums {
		if len(checksums[i]) != 64 {
			return nil, fmt.Errorf("invalid checksum '%s' found in '%s'", checksums[i], checksumDir)
		}
		checksumMap[checksums[i]] = struct{}{}
	}
	return checksumMap, nil
}

func (sc *sshClient) cleanUpRemainingCachedEntries(checksumDir string, checksumHash map[string]struct{}) (e error) {
	invalidCacheEntries := make([]string, 0, len(checksumHash))
	for k, _ := range checksumHash {
		invalidCacheEntries = append(invalidCacheEntries, fmt.Sprintf("%s.done", k))
	}
	if sc.provisionOptions.DryRun {
		(&Message{key: MessageCleanupCacheEntries, invalidatedCachentries: invalidCacheEntries, host: sc.host}).publish(".dryrun")
	} else {
		cmd := fmt.Sprintf("cd %s && rm -f *.failed %s", checksumDir, strings.Join(invalidCacheEntries, " "))
		m := &Message{command: cmd, host: sc.host, key: MessageUrknallInternal}
		m.publish("started")
		result := sc.executeCommand(cmd)
		m.sshResult = result
		m.publish("finished")
	}
	return nil
}

func (sc *sshClient) writeChecksumFile(checksumDir, checksum string, failed bool, logMsg string, response *gossh.Result) {
	tmpChecksumFiles := "/tmp/" + sc.host.user() + "." + checksum + ".std*"
	checksumFile := checksumDir + "/" + checksum
	if failed {
		checksumFile += ".failed"
	} else {
		checksumFile += ".done"
	}

	// Whoa, super hacky stuff to get the command to the checksum file. The command might contain a lot of stuff, like
	// apostrophes and the like, that would totally nuke a quoted string. Though there is a here doc.
	c := []string{
		fmt.Sprintf(`cat %s | sort >> %s`, tmpChecksumFiles, checksumFile),
		fmt.Sprintf(`rm -f %s`, tmpChecksumFiles),
	}
	sc.executeCommand(fmt.Sprintf("cat <<EOF_COMMAND > %s && %s\n%s\nEOF_COMMAND\n", checksumFile, strings.Join(c, " && "), logMsg))
}

type taskData struct {
	command  cmd.Command // The command to be executed.
	checksum string      // The checksum of the command.
	runlist  *Runlist
}

func (data *taskData) Command() cmd.Command {
	return data.command
}

func (sc *sshClient) buildTasksForRunlist(rl *Runlist) (tasks []*taskData) {
	tasks = make([]*taskData, 0, len(rl.commands))

	cmdHash := sha256.New()
	for i := range rl.commands {
		rawCmd := rl.commands[i].Shell()
		cmdHash.Write([]byte(rawCmd))

		task := &taskData{runlist: rl, command: rl.commands[i], checksum: fmt.Sprintf("%x", cmdHash.Sum(nil))}
		tasks = append(tasks, task)
	}
	return tasks
}
<|endoftext|>


<commit_before>package steam

import (
	"code.google.com/p/goprotobuf/proto"
	"crypto/aes"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"github.com/macb/go-steam/cryptoutil"
	. "github.com/macb/go-steam/internal"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"sync/atomic"
)

type Web struct {
	// The `sessionid` cookie required to use the steam website.
	WebSessionId string
	// The `steamLogin` cookie required to use the steam website.
	// It is only available after calling LogOn().
	SteamLogin string

	webLoginKey  string
	relogOnNonce uint32

	client *Client
}

func (w *Web) HandlePacket(packet *PacketMsg) {
	switch packet.EMsg {
	case EMsg_ClientNewLoginKey:
		w.handleNewLoginKey(packet)
	case EMsg_ClientRequestWebAPIAuthenticateUserNonceResponse:
		w.handleAuthNonceResponse(packet)
	}
}

type WebLoggedOnEvent struct{}

// Fetches the `steamLogin` cookie. This may only be called after the first
// WebSessionIdEvent or it will panic.
func (w *Web) LogOn() {
	if w.webLoginKey == "" {
		panic("SteamWeb: webLoginKey not initialized!")
	}

	go func() {
		// retry three times. yes, I know about loops.
		err := w.apiLogOn()
		if err != nil {
			err = w.apiLogOn()
			if err != nil {
				err = w.apiLogOn()
			}
		}
		if err != nil {
			w.client.Errorf("web: Error logging on: %v", err)
			return
		}
	}()
}

func (w *Web) apiLogOn() error {
	sessionKey := make([]byte, 32)
	rand.Read(sessionKey)

	cryptedSessionKey := cryptoutil.RSAEncrypt(GetPublicKey(EUniverse_Public), sessionKey)
	ciph, _ := aes.NewCipher(sessionKey)
	cryptedLoginKey := cryptoutil.SymmetricEncrypt(ciph, []byte(w.webLoginKey))

	data := make(url.Values)
	data.Add("format", "json")
	data.Add("steamid", strconv.FormatUint(uint64(w.client.SteamId()), 10))
	data.Add("sessionkey", string(cryptedSessionKey))
	data.Add("encrypted_loginkey", string(cryptedLoginKey))
	resp, err := http.PostForm("http://api.steampowered.com/ISteamUserAuth/AuthenticateUser/v0001", data)
	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		// our web session id has expired, request a new one
		w.client.Write(NewClientMsgProtobuf(EMsg_ClientRequestWebAPIAuthenticateUserNonce, new(CMsgClientRequestWebAPIAuthenticateUserNonce)))
		atomic.StoreUint32(&w.relogOnNonce, 1)
		return nil
	}

	result := new(struct {
		Authenticateuser struct {
			Token string
		}
	})
	b, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, result)
	if err != nil {
		return err
	}

	w.SteamLogin = result.Authenticateuser.Token

	w.client.Emit(new(WebLoggedOnEvent))
	return nil
}

type WebSessionIdEvent struct{}

func (w *Web) handleNewLoginKey(packet *PacketMsg) {
	msg := new(CMsgClientNewLoginKey)
	packet.ReadProtoMsg(msg)

	w.client.Write(NewClientMsgProtobuf(EMsg_ClientNewLoginKeyAccepted, &CMsgClientNewLoginKeyAccepted{
		UniqueId: proto.Uint32(msg.GetUniqueId()),
	}))

	w.webLoginKey = msg.GetLoginKey()
	// number -> string -> bytes -> base64
	w.WebSessionId = base64.StdEncoding.EncodeToString([]byte(strconv.FormatUint(uint64(msg.GetUniqueId()), 10)))

	w.client.Emit(new(WebSessionIdEvent))
}

func (w *Web) handleAuthNonceResponse(packet *PacketMsg) {
	// this has to be the best name for a message yet.
	msg := new(CMsgClientRequestWebAPIAuthenticateUserNonceResponse)
	packet.ReadProtoMsg(msg)
	w.WebSessionId = msg.GetWebapiAuthenticateUserNonce()

	// if the nonce was specifically requested in apiLogOn(),
	// don't emit an event.
	if atomic.CompareAndSwapUint32(&w.relogOnNonce, 1, 0) {
		w.LogOn()
	} else {
		w.client.Emit(new(WebSessionIdEvent))
	}
}
<commit_msg>Use WebSessionId instead of webLoginKey. webLoginKey never changes after initial login.<commit_after>package steam

import (
	"code.google.com/p/goprotobuf/proto"
	"crypto/aes"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"github.com/macb/go-steam/cryptoutil"
	. "github.com/macb/go-steam/internal"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"sync/atomic"
)

type Web struct {
	// The `sessionid` cookie required to use the steam website.
	WebSessionId string
	// The `steamLogin` cookie required to use the steam website.
	// It is only available after calling LogOn().
	SteamLogin string

	webLoginKey  string
	relogOnNonce uint32

	client *Client
}

func (w *Web) HandlePacket(packet *PacketMsg) {
	switch packet.EMsg {
	case EMsg_ClientNewLoginKey:
		w.handleNewLoginKey(packet)
	case EMsg_ClientRequestWebAPIAuthenticateUserNonceResponse:
		w.handleAuthNonceResponse(packet)
	}
}

type WebLoggedOnEvent struct{}

// Fetches the `steamLogin` cookie. This may only be called after the first
// WebSessionIdEvent or it will panic.
func (w *Web) LogOn() {
	if w.webLoginKey == "" {
		panic("SteamWeb: webLoginKey not initialized!")
	}

	go func() {
		// retry three times. yes, I know about loops.
		err := w.apiLogOn()
		if err != nil {
			err = w.apiLogOn()
			if err != nil {
				err = w.apiLogOn()
			}
		}
		if err != nil {
			w.client.Errorf("web: Error logging on: %v", err)
			return
		}
	}()
}

func (w *Web) apiLogOn() error {
	sessionKey := make([]byte, 32)
	rand.Read(sessionKey)

	cryptedSessionKey := cryptoutil.RSAEncrypt(GetPublicKey(EUniverse_Public), sessionKey)
	ciph, _ := aes.NewCipher(sessionKey)
	cryptedLoginKey := cryptoutil.SymmetricEncrypt(ciph, []byte(w.WebSessionId))
	data := make(url.Values)
	data.Add("format", "json")
	data.Add("steamid", strconv.FormatUint(uint64(w.client.SteamId()), 10))
	data.Add("sessionkey", string(cryptedSessionKey))
	data.Add("encrypted_loginkey", string(cryptedLoginKey))
	resp, err := http.PostForm("http://api.steampowered.com/ISteamUserAuth/AuthenticateUser/v0001", data)
	if err != nil {
		return err
	}

	if resp.StatusCode != 200 {
		// our web session id has expired, request a new one
		w.client.Write(NewClientMsgProtobuf(EMsg_ClientRequestWebAPIAuthenticateUserNonce, new(CMsgClientRequestWebAPIAuthenticateUserNonce)))
		atomic.StoreUint32(&w.relogOnNonce, 1)
		return nil
	}

	result := new(struct {
		Authenticateuser struct {
			Token string
		}
	})
	b, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, result)
	if err != nil {
		return err
	}

	w.SteamLogin = result.Authenticateuser.Token

	w.client.Emit(new(WebLoggedOnEvent))
	return nil
}

type WebSessionIdEvent struct{}

func (w *Web) handleNewLoginKey(packet *PacketMsg) {
	msg := new(CMsgClientNewLoginKey)
	packet.ReadProtoMsg(msg)

	w.client.Write(NewClientMsgProtobuf(EMsg_ClientNewLoginKeyAccepted, &CMsgClientNewLoginKeyAccepted{
		UniqueId: proto.Uint32(msg.GetUniqueId()),
	}))

	w.webLoginKey = msg.GetLoginKey()
	// number -> string -> bytes -> base64
	w.WebSessionId = base64.StdEncoding.EncodeToString([]byte(strconv.FormatUint(uint64(msg.GetUniqueId()), 10)))

	w.client.Emit(new(WebSessionIdEvent))
}

func (w *Web) handleAuthNonceResponse(packet *PacketMsg) {
	// this has to be the best name for a message yet.
	msg := new(CMsgClientRequestWebAPIAuthenticateUserNonceResponse)
	packet.ReadProtoMsg(msg)
	w.WebSessionId = msg.GetWebapiAuthenticateUserNonce()

	// if the nonce was specifically requested in apiLogOn(),
	// don't emit an event.
	if atomic.CompareAndSwapUint32(&w.relogOnNonce, 1, 0) {
		w.LogOn()
	} else {
		w.client.Emit(new(WebSessionIdEvent))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"text/template"
)

// Init of the Web Page template.
var tpl = template.Must(
	template.New("main").Delims("<%", "%>").Funcs(template.FuncMap{"json": json.Marshal}).Parse(`
	<!DOCTYPE html>

Pingo

Total number of targets : {{targets.length}}

				Search: <input ng-model="q"/>

							Name
							up
							up

						Addr
						Online
						Since
						Last Check
						Message

						{{t.Target.Name}}
						{{t.Target.Addr}}

							online
							offline

						{{t.Since | dateFormat}} ({{t.Since | dateFromNow}})
						{{t.LastCheck | dateFromNow:true}}
						{{t.ErrorMsg}}

	`))

func startHttp(port int, state *State) {
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		state.Lock()
		defer state.Unlock()

		err := tpl.Execute(w, state)
		if err != nil {
			log.Fatal(err)
		}
	})

	s := fmt.Sprintf(":%d", port)
	log.Printf("Status page available at: http://localhost%s/status", s)

	err := http.ListenAndServe(s, nil)
	if err != nil {
		log.Fatalf("HTTP server error, %s", err)
	}
}
<commit_msg>Update web status<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"text/template"
)

// Init of the Web Page template.
var tpl = template.Must(
	template.New("main").Delims("<%", "%>").Funcs(template.FuncMap{"json": json.Marshal}).Parse(`
	<!DOCTYPE html>

Pingo2

Total number of targets : {{targets.length}}

				Search: <input ng-model="q" placeholder="filter keyword">

							Name
							up
							up

						Addr
						Online
						Since
						Last Check
						Message

						{{t.Target.Name}}
						{{t.Target.Addr}}

							online
							offline

						{{t.Since | dateFormat}} ({{t.Since | dateFromNow}})
						{{t.LastCheck | dateFromNow:true}}
						{{t.ErrorMsg}}

	`))

func startHttp(port int, state *State) {
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		state.Lock()
		defer state.Unlock()

		err := tpl.Execute(w, state)
		if err != nil {
			log.Fatal(err)
		}
	})

	s := fmt.Sprintf(":%d", port)
	log.Printf("Status page available at: http://localhost%s/status", s)

	err := http.ListenAndServe(s, nil)
	if err != nil {
		log.Fatalf("HTTP server error, %s", err)
	}
}
<|endoftext|>


<commit_before>package main

// Import formatting and IO libraries
import (
	"html/template"
	"io/ioutil"
	"net/http"
)

// Define a structure to hold our page
type Page struct {
	Title string
	Body  []byte // IO libs expect a byte slice rather than a string
}

// Add a save method to our Page struct so we can persist our data
// This method's signature reads: "This is a method named save that takes as its receiver p, a pointer to Page . It takes no parameters, and returns a value of type error."
func (p *Page) save() error {
	filename := p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

// Load pages too
func loadPage(title string) (*Page, error) {
	filename := title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Page{Title: title, Body: body}, nil
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	t, err := template.ParseFiles(tmpl + ".html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	err = t.Execute(w, p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	t.Execute(w, p)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/view/"):]
	p, err := loadPage(title)
	if err != nil {
		http.Redirect(w, r, "/edit/"+title, http.StatusFound)
		return
	}
	renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/edit/"):]
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}
	renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/save/"):]
	body := r.FormValue("body")
	p := &Page{Title: title, Body: []byte(body)}
	err := p.save()
        if err != nil {
          http.Error(w, err.Error(), http.StatusInternalServerError)
          return
        }
	http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

func main() {
	http.HandleFunc("/view/", viewHandler)
	http.HandleFunc("/edit/", editHandler)
	http.HandleFunc("/save/", saveHandler)
	http.ListenAndServe(":8080", nil)
}
<commit_msg>Cache templates on initialization.<commit_after>package main

// Import formatting and IO libraries
import (
	"html/template"
	"io/ioutil"
	"net/http"
)

// Define a structure to hold our page
type Page struct {
	Title string
	Body  []byte // IO libs expect a byte slice rather than a string
}

// Add a save method to our Page struct so we can persist our data
// This method's signature reads: "This is a method named save that takes as its receiver p, a pointer to Page . It takes no parameters, and returns a value of type error."
func (p *Page) save() error {
	filename := p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

// Load pages too
func loadPage(title string) (*Page, error) {
	filename := title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Page{Title: title, Body: body}, nil
}

var templates = template.Must(template.ParseFiles("edit.html", "view.html"))
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	err = templates.ExecuteTemplate(w, tmpl+".html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	t.Execute(w, p)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/view/"):]
	p, err := loadPage(title)
	if err != nil {
		http.Redirect(w, r, "/edit/"+title, http.StatusFound)
		return
	}
	renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/edit/"):]
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}
	renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/save/"):]
	body := r.FormValue("body")
	p := &Page{Title: title, Body: []byte(body)}
	err := p.save()
        if err != nil {
          http.Error(w, err.Error(), http.StatusInternalServerError)
          return
        }
	http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

func main() {
	http.HandleFunc("/view/", viewHandler)
	http.HandleFunc("/edit/", editHandler)
	http.HandleFunc("/save/", saveHandler)
	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"image/color"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"

	"github.com/MJKWoolnough/byteio"
	"github.com/MJKWoolnough/ora"
	"golang.org/x/net/websocket"
)

func writeError(w *byteio.StickyWriter, err error) {
	w.WriteUint8(0)
	errStr := []byte(err.Error())
	w.WriteUint16(uint16(len(errStr)))
	w.Writer.Write(errStr)
	fmt.Println("error:", err)
}

type paint struct {
	color.Color
	X, Y int32
	Err  error
}

func socketHandler(conn *websocket.Conn) {
	conn.PayloadType = websocket.BinaryFrame
	r := byteio.StickyReader{Reader: &byteio.LittleEndianReader{conn}}
	w := byteio.StickyWriter{Writer: &byteio.LittleEndianWriter{Writer: conn}}
	length := r.ReadInt64()
	if r.Err != nil {
		writeError(&w, r.Err)
		return
	}
	f, err := ioutil.TempFile("", "mineWebGen")
	if err != nil {
		writeError(&w, err)
		return
	}
	defer os.Remove(f.Name())
	defer f.Close()
	n, err := io.Copy(f, io.LimitReader(conn, int64(length)))
	if err != nil {
		writeError(&w, err)
		return
	}
	if n != length {
		writeError(&w, io.EOF)
		return
	}
	f.Seek(0, 0)
	o, err := ora.Open(f, length)
	if err != nil {
		writeError(&w, err)
		return
	}
	if o.Layer("terrain") == nil {
		writeError(&w, layerError{"terrain"})
		return
	}
	if o.Layer("height") == nil {
		writeError(&w, layerError{"height"})
		return
	}
	b := o.Bounds()
	w.WriteUint8(1)
	w.WriteInt32(int32(b.Max.X) >> 4)
	w.WriteInt32(int32(b.Max.Y) >> 4)
	if w.Err != nil {
		writeError(&w, w.Err)
		return
	}
	c := make(chan paint, 1024)
	go buildMap(o, c)
	for p := range c {
		if p.Err != nil {
			writeError(&w, p.Err)
			return
		}
		w.WriteUint8(1)
		w.WriteInt32(p.X)
		w.WriteInt32(p.Y)
		r, g, b, a := p.Color.RGBA()
		w.WriteUint8(uint8(r >> 8))
		w.WriteUint8(uint8(g >> 8))
		w.WriteUint8(uint8(b >> 8))
		w.WriteUint8(uint8(a >> 8))
		if w.Err != nil {
			writeError(&w, w.Err)
			for range c {
			}
			return
		}
	}
	w.WriteUint8(255)
}

type layerError struct {
	name string
}

func (l layerError) Error() string {
	return "missing layer: " + l.name
}

var port = flag.Uint("-p", 8080, "server port")

func main() {
	http.Handle("/socket", websocket.Handler(socketHandler))
	http.Handle("/", http.FileServer(dir))
	l, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Println(err)
		return
	}

	c := make(chan os.Signal, 1)
	go func() {
		defer l.Close()
		log.Println("Server Started")
		signal.Notify(c, os.Interrupt)
		defer signal.Stop(c)
		<-c
		close(c)
		log.Println("Closing")
	}()

	err = http.Serve(l, nil)
	select {
	case <-c:
	default:
		close(c)
		log.Println(err)
	}
}
<commit_msg>Added message sending support<commit_after>package main

import (
	"flag"
	"fmt"
	"image/color"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"

	"github.com/MJKWoolnough/byteio"
	"github.com/MJKWoolnough/ora"
	"golang.org/x/net/websocket"
)

func writeError(w *byteio.StickyWriter, err error) {
	w.WriteUint8(0)
	errStr := []byte(err.Error())
	w.WriteUint16(uint16(len(errStr)))
	w.Write(errStr)
	fmt.Println("error:", err)
}

type paint struct {
	color.Color
	X, Y int32
	Err  error
}

func socketHandler(conn *websocket.Conn) {
	conn.PayloadType = websocket.BinaryFrame
	r := byteio.StickyReader{Reader: &byteio.LittleEndianReader{conn}}
	w := byteio.StickyWriter{Writer: &byteio.LittleEndianWriter{Writer: conn}}
	length := r.ReadInt64()
	if r.Err != nil {
		writeError(&w, r.Err)
		return
	}
	f, err := ioutil.TempFile("", "mineWebGen")
	if err != nil {
		writeError(&w, err)
		return
	}
	defer os.Remove(f.Name())
	defer f.Close()
	n, err := io.Copy(f, io.LimitReader(conn, int64(length)))
	if err != nil {
		writeError(&w, err)
		return
	}
	if n != length {
		writeError(&w, io.EOF)
		return
	}
	f.Seek(0, 0)
	o, err := ora.Open(f, length)
	if err != nil {
		writeError(&w, err)
		return
	}
	if o.Layer("terrain") == nil {
		writeError(&w, layerError{"terrain"})
		return
	}
	if o.Layer("height") == nil {
		writeError(&w, layerError{"height"})
		return
	}
	b := o.Bounds()
	w.WriteUint8(1)
	w.WriteInt32(int32(b.Max.X) >> 4)
	w.WriteInt32(int32(b.Max.Y) >> 4)
	if w.Err != nil {
		writeError(&w, w.Err)
		return
	}
	c := make(chan paint, 1024)
	m := make(chan string, 1024)
	go buildMap(o, c, m)
Loop:
	for {
		select {
		case p := <-c:
			if p.Err != nil {
				writeError(&w, p.Err)
				return
			}
			if p.Color == nil {
				break Loop
			}
			w.WriteUint8(1)
			w.WriteInt32(p.X)
			w.WriteInt32(p.Y)
			r, g, b, a := p.RGBA()
			w.WriteUint8(uint8(r >> 8))
			w.WriteUint8(uint8(g >> 8))
			w.WriteUint8(uint8(b >> 8))
			w.WriteUint8(uint8(a >> 8))
		case message := <-m:
			w.WriteUint8(2)
			w.WriteUint16(uint16(len(message)))
			w.Write([]byte(message))
		}
	}
	w.WriteUint8(255)
}

type layerError struct {
	name string
}

func (l layerError) Error() string {
	return "missing layer: " + l.name
}

var port = flag.Uint("-p", 8080, "server port")

func main() {
	http.Handle("/socket", websocket.Handler(socketHandler))
	http.Handle("/", http.FileServer(dir))
	l, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Println(err)
		return
	}

	c := make(chan os.Signal, 1)
	go func() {
		defer l.Close()
		log.Println("Server Started")
		signal.Notify(c, os.Interrupt)
		defer signal.Stop(c)
		<-c
		close(c)
		log.Println("Closing")
	}()

	err = http.Serve(l, nil)
	select {
	case <-c:
	default:
		close(c)
		log.Println(err)
	}
}
<|endoftext|>