<commit_before>package para

import "sync"

type Fetcher struct {
	wg             sync.WaitGroup
	cleanupWaiting sync.Once
	initClose      sync.Once
	resultChan     chan *Result
	closeChan      chan struct{}
	// Public channels
	Get chan *Result
	// optional channel to notify outside when clean up is complete
	Done chan struct{}
}

type Result struct {
	err      error
	response string
}

func NewFetcher() *Fetcher {
	f := &Fetcher{
		wg:             sync.WaitGroup{},
		cleanupWaiting: sync.Once{},
		initClose:      sync.Once{},
		closeChan:      make(chan struct{}),
		resultChan:     make(chan *Result, 10),

		Get:  make(chan *Result),
		Done: make(chan struct{}),
	}
	go f.Listen()
	return f
}

// Fetch is called by the thread initiating the fanout.
// It "forks" and starts up the described worker.
//
// The Worker should implement its own timeout functionality
//
// TODO what should be the Format for the worker func?
func (f *Fetcher) Fetch(worker func() (string, error)) {
	f.wg.Add(1)
	f.cleanupWaiting.Do(func() { go f.waitAndCleanup(f.Done) })
	go func(worker func() (string, error)) {
		r, e := worker()
		select {
		case <-f.closeChan:
			f.wg.Done()
		default:
			f.resultChan <- &Result{
				err:      e,
				response: r,
			}
		}
	}(worker)
}

func (f *Fetcher) waitAndCleanup(doneChan chan struct{}) {
	// Wait until all workers have returned or a successful result has come
	// and workers can shutdown
	f.wg.Wait()
	// then tell the listen loop to close
	close(f.resultChan)
	// and tell the outside we are cleaned up.
	close(doneChan)
}

// Listen validates the results and initiates shutdown if there is a valid result.
func (f *Fetcher) Listen() {
	var lastResult *Result
	for r := range f.resultChan {
		f.wg.Done()
		lastResult = r
		if r.err == nil {
			f.initClose.Do(func() {
				close(f.closeChan)
				f.Get <- r
			})
		}
	}
	f.Get <- lastResult
}
<commit_msg>updated comment<commit_after>package para

import "sync"

type Fetcher struct {
	wg             sync.WaitGroup
	cleanupWaiting sync.Once
	initClose      sync.Once
	resultChan     chan *Result
	closeChan      chan struct{}
	// Public channels
	Get chan *Result
	// optional channel to notify outside when clean up is complete
	Done chan struct{}
}

type Result struct {
	err      error
	response string
}

func NewFetcher() *Fetcher {
	f := &Fetcher{
		wg:             sync.WaitGroup{},
		cleanupWaiting: sync.Once{},
		initClose:      sync.Once{},
		closeChan:      make(chan struct{}),
		resultChan:     make(chan *Result, 10),

		Get:  make(chan *Result),
		Done: make(chan struct{}),
	}
	go f.Listen()
	return f
}

// Fetch is called by the thread initiating the fanout.
// It "forks" and starts up the described worker.
//
// The Worker should implement its own timeout functionality
//
// TODO what should be the Format for the worker func?
func (f *Fetcher) Fetch(worker func() (string, error)) {
	f.wg.Add(1)
	f.cleanupWaiting.Do(func() { go f.waitAndCleanup(f.Done) })
	go func(worker func() (string, error)) {
		r, e := worker()
		select {
		case <-f.closeChan:
			f.wg.Done()
		default:
			f.resultChan <- &Result{
				err:      e,
				response: r,
			}
		}
	}(worker)
}

func (f *Fetcher) waitAndCleanup(doneChan chan struct{}) {
	// Wait until all workers have returned or a successful result has come
	// and workers can shutdown
	f.wg.Wait()
	// then tell the listen loop to close
	close(f.resultChan)
	// and tell the outside we are cleaned up.
	close(doneChan)
}

// Listen validates the results and initiates shutdown if there is a valid result.
// If no valid result is found it emits the last failing result.
func (f *Fetcher) Listen() {
	var lastResult *Result
	for r := range f.resultChan {
		f.wg.Done()
		lastResult = r
		if r.err == nil {
			f.initClose.Do(func() {
				close(f.closeChan)
				f.Get <- r
			})
		}
	}
	f.Get <- lastResult
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/realglobe-Inc/edo/util"
	"github.com/realglobe-Inc/go-lib-rg/erro"
	"github.com/realglobe-Inc/go-lib-rg/rglog/level"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type parameters struct {
	// 画面表示ログ。
	consLv level.Level

	// 追加ログ種別。
	logType string
	// 追加ログ表示重要度。
	logLv level.Level
	// ログファイルパス。
	logPath string
	// fluentd アドレス。
	fluAddr string
	// fluentd 用タグ。
	fluTag string

	// 秘密鍵置き場。
	priKeyContType string
	// ファイルベース秘密鍵置き場。
	priKeyContPath string

	// ソケット種別。
	socType string
	// UNIX ソケット。
	socPath string
	// TCP ソケット。
	socPort int

	// プロトコル種別。
	protType string

	// キャッシュを最新とみなす期間。
	caStaleDur time.Duration
	// キャッシュを廃棄するまでの期間。
	caExpiDur time.Duration

	// 称する TA の ID。
	taId string

	// 署名に使うハッシュ関数。
	hashName string

	// 有効期限ギリギリのセッションを避けるための遊び。
	sessMargin time.Duration

	// 同一ホスト用の http.Client の保持期間。
	cliExpiDur time.Duration

	// セッションを事前に検査するボディサイズの下限。
	threSize int

	// SSL 証明書を検証しない。
	noVerify bool
}

func parseParameters(args ...string) (param *parameters, err error) {

	const label = "edo-access-proxy"

	flags := util.NewFlagSet(label+" parameters", flag.ExitOnError)
	flags.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage:")
		fmt.Fprintln(os.Stderr, "  "+args[0]+" [{FLAG}...]")
		fmt.Fprintln(os.Stderr, "FLAG:")
		flags.PrintDefaults()
	}

	param = &parameters{}

	flags.Var(level.Var(&param.consLv, level.INFO), "consLv", "Console log level.")
	flags.StringVar(&param.logType, "logType", "", "Extra log type.")
	flags.Var(level.Var(&param.logLv, level.ALL), "logLv", "Extra log level.")
	flags.StringVar(&param.logPath, "logPath", filepath.Join(filepath.Dir(os.Args[0]), "log", label+".log"), "File log path.")
	flags.StringVar(&param.fluAddr, "fluAddr", "localhost:24224", "fluentd address.")
	flags.StringVar(&param.fluTag, "fluTag", "edo."+label, "fluentd tag.")

	flags.StringVar(&param.priKeyContType, "priKeyContType", "file", "Private key container type.")
	flags.StringVar(&param.priKeyContPath, "priKeyContPath", filepath.Join(filepath.Dir(os.Args[0]), "private_keys"), "Private key container directory.")

	flags.StringVar(&param.socType, "socType", "tcp", "Socket type.")
	flags.StringVar(&param.socPath, "socPath", filepath.Join(filepath.Dir(os.Args[0]), "run", label+".soc"), "UNIX socket path.")
	flags.IntVar(&param.socPort, "socPort", 16050, "TCP socket port.")
	flags.StringVar(&param.protType, "protType", "http", "Protocol type.")

	flags.DurationVar(&param.caStaleDur, "caStaleDur", 5*time.Minute, "Cache fresh duration.")
	flags.DurationVar(&param.caExpiDur, "caExpiDur", 30*time.Minute, "Cache expiration duration.")

	flags.StringVar(&param.taId, "taId", "", "Default TA ID.")
	flags.StringVar(&param.hashName, "hashName", "sha256", "Sign hash type.")

	flags.DurationVar(&param.sessMargin, "sessMargin", time.Minute, "Margin for session expiration duration.")
	flags.DurationVar(&param.cliExpiDur, "cliExpiDur", 10*time.Minute, "Client expiration duration.")
	flags.IntVar(&param.threSize, "threSize", 8192, "Maximum byte size of request body for skipping session check.")
	flags.BoolVar(&param.noVerify, "noVerify", false, "Skipping SSL verification.")

	var config string
	flags.StringVar(&config, "f", "", "Config file path.")

	// 実行引数を読んで、設定ファイルを指定させてから、
	// 設定ファイルを読んで、また実行引数を読む。
	flags.Parse(args[1:])
	if config != "" {
		if buff, err := ioutil.ReadFile(config); err != nil {
			if !os.IsNotExist(err) {
				return nil, erro.Wrap(err)
			}
			log.Warn("Config file " + config + " is not exist.")
		} else {
			flags.CompleteParse(strings.Fields(string(buff)))
		}
	}
	flags.Parse(args[1:])

	if l := len(flags.Args()); l > 0 {
		log.Warn("Ignore extra parameters ", flags.Args(), ".")
	}

	return param, nil
}
<commit_msg>設定ファイルを共有する必要がなくなっていたので共有するのはやめた<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/realglobe-Inc/go-lib-rg/erro"
	"github.com/realglobe-Inc/go-lib-rg/rglog/level"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type parameters struct {
	// 画面表示ログ。
	consLv level.Level

	// 追加ログ種別。
	logType string
	// 追加ログ表示重要度。
	logLv level.Level
	// ログファイルパス。
	logPath string
	// fluentd アドレス。
	fluAddr string
	// fluentd 用タグ。
	fluTag string

	// 秘密鍵置き場。
	priKeyContType string
	// ファイルベース秘密鍵置き場。
	priKeyContPath string

	// ソケット種別。
	socType string
	// UNIX ソケット。
	socPath string
	// TCP ソケット。
	socPort int

	// プロトコル種別。
	protType string

	// キャッシュを最新とみなす期間。
	caStaleDur time.Duration
	// キャッシュを廃棄するまでの期間。
	caExpiDur time.Duration

	// 称する TA の ID。
	taId string

	// 署名に使うハッシュ関数。
	hashName string

	// 有効期限ギリギリのセッションを避けるための遊び。
	sessMargin time.Duration

	// 同一ホスト用の http.Client の保持期間。
	cliExpiDur time.Duration

	// セッションを事前に検査するボディサイズの下限。
	threSize int

	// SSL 証明書を検証しない。
	noVerify bool
}

func parseParameters(args ...string) (param *parameters, err error) {

	const label = "edo-access-proxy"

	flags := flag.NewFlagSet(label+" parameters", flag.ExitOnError)
	flags.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage:")
		fmt.Fprintln(os.Stderr, "  "+args[0]+" [{FLAG}...]")
		fmt.Fprintln(os.Stderr, "FLAG:")
		flags.PrintDefaults()
	}

	param = &parameters{}

	flags.Var(level.Var(&param.consLv, level.INFO), "consLv", "Console log level.")
	flags.StringVar(&param.logType, "logType", "", "Extra log type.")
	flags.Var(level.Var(&param.logLv, level.ALL), "logLv", "Extra log level.")
	flags.StringVar(&param.logPath, "logPath", filepath.Join(filepath.Dir(os.Args[0]), "log", label+".log"), "File log path.")
	flags.StringVar(&param.fluAddr, "fluAddr", "localhost:24224", "fluentd address.")
	flags.StringVar(&param.fluTag, "fluTag", "edo."+label, "fluentd tag.")

	flags.StringVar(&param.priKeyContType, "priKeyContType", "file", "Private key container type.")
	flags.StringVar(&param.priKeyContPath, "priKeyContPath", filepath.Join(filepath.Dir(os.Args[0]), "private_keys"), "Private key container directory.")

	flags.StringVar(&param.socType, "socType", "tcp", "Socket type.")
	flags.StringVar(&param.socPath, "socPath", filepath.Join(filepath.Dir(os.Args[0]), "run", label+".soc"), "UNIX socket path.")
	flags.IntVar(&param.socPort, "socPort", 16050, "TCP socket port.")
	flags.StringVar(&param.protType, "protType", "http", "Protocol type.")

	flags.DurationVar(&param.caStaleDur, "caStaleDur", 5*time.Minute, "Cache fresh duration.")
	flags.DurationVar(&param.caExpiDur, "caExpiDur", 30*time.Minute, "Cache expiration duration.")

	flags.StringVar(&param.taId, "taId", "", "Default TA ID.")
	flags.StringVar(&param.hashName, "hashName", "sha256", "Sign hash type.")

	flags.DurationVar(&param.sessMargin, "sessMargin", time.Minute, "Margin for session expiration duration.")
	flags.DurationVar(&param.cliExpiDur, "cliExpiDur", 10*time.Minute, "Client expiration duration.")
	flags.IntVar(&param.threSize, "threSize", 8192, "Maximum byte size of request body for skipping session check.")
	flags.BoolVar(&param.noVerify, "noVerify", false, "Skipping SSL verification.")

	var config string
	flags.StringVar(&config, "f", "", "Config file path.")

	// 実行引数を読んで、設定ファイルを指定させてから、
	// 設定ファイルを読んで、また実行引数を読む。
	flags.Parse(args[1:])
	if config != "" {
		if buff, err := ioutil.ReadFile(config); err != nil {
			if !os.IsNotExist(err) {
				return nil, erro.Wrap(err)
			}
			log.Warn("Config file " + config + " is not exist.")
		} else {
			flags.Parse(strings.Fields(string(buff)))
		}
	}
	flags.Parse(args[1:])

	if l := len(flags.Args()); l > 0 {
		log.Warn("Ignore extra parameters ", flags.Args(), ".")
	}

	return param, nil
}
<|endoftext|>


<commit_before>package markdown

import (
	"bytes"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/leeola/muta"
	"github.com/russross/blackfriday"
)

// Called when our Streamer is the Generator
func generate() (*muta.FileInfo, []byte, error) {
	return nil, nil, nil
}

// Called when data is coming in
func buffer(b *bytes.Buffer, chunk []byte) (*muta.FileInfo, []byte, error) {
	_, err := b.Write(chunk)
	// Note that by returning `nil` File, we signal "End of Stream" (EOS).
	// This causes the Stream to not call any Streamers *after* this
	// stream.
	//
	// We do this because we want to buffer all of the incoming data for
	// each file. Once we collect it all, we modify it, and then return
	// it.
	return nil, nil, err
}

// The incoming data stream for the given file is done, we can
// compile the markdown and return our modified data
func write(b *bytes.Buffer, fi *muta.FileInfo, _ []byte) (*muta.FileInfo, []byte, error) {
	if filepath.Ext(fi.Name) != ".html" {
		fi.Name = strings.Replace(fi.Name, filepath.Ext(fi.Name), ".html", 1)
	}

	// If there is no data to write, call EOF
	if b.Len() == 0 {
		return fi, nil, nil
	}

	rawMarkdown, err := ioutil.ReadAll(b)
	if err != nil {
		return fi, nil, err
	}

	html := blackfriday.MarkdownBasic(rawMarkdown)
	return fi, html, nil
}

func Markdown() muta.Streamer {
	var b bytes.Buffer
	return func(fi *muta.FileInfo, chunk []byte) (*muta.FileInfo, []byte, error) {
		switch {
		case fi == nil:
			// If fi is nil, Markdown() is being asked to generate files.
			return generate()

		case filepath.Ext(fi.Name) != ".md":
			// If the file is not Markdown, pass it through untouched.
			return fi, chunk, nil

		case chunk == nil:
			// If chunk is nil, we're at the EOF for the incoming data for *fi
			return write(&b, fi, chunk)

		default:
			// If chunk isn't nil, buffer the data
			return buffer(&b, chunk)
		}
	}
}
<commit_msg>Updated the plugin to use the new Streamer interface<commit_after>package markdown

import (
	"bytes"
	"io/ioutil"
	"path/filepath"
	"strings"

	"github.com/leeola/muta"
	"github.com/russross/blackfriday"
)

// Called when our Streamer is the Generator
func generate() (*muta.FileInfo, []byte, error) {
	return nil, nil, nil
}

// Called when data is coming in
func buffer(b *bytes.Buffer, chunk []byte) (*muta.FileInfo, []byte, error) {
	_, err := b.Write(chunk)
	// Note that by returning `nil` File, we signal "End of Stream" (EOS).
	// This causes the Stream to not call any Streamers *after* this
	// stream.
	//
	// We do this because we want to buffer all of the incoming data for
	// each file. Once we collect it all, we modify it, and then return
	// it.
	return nil, nil, err
}

// The incoming data stream for the given file is done, we can
// compile the markdown and return our modified data
func write(b *bytes.Buffer, fi *muta.FileInfo, _ []byte) (*muta.FileInfo, []byte, error) {
	if filepath.Ext(fi.Name) != ".html" {
		fi.Name = strings.Replace(fi.Name, filepath.Ext(fi.Name), ".html", 1)
	}

	// If there is no data to write, call EOF
	if b.Len() == 0 {
		return fi, nil, nil
	}

	rawMarkdown, err := ioutil.ReadAll(b)
	if err != nil {
		return fi, nil, err
	}

	html := blackfriday.MarkdownBasic(rawMarkdown)
	return fi, html, nil
}

func Markdown() muta.Streamer {
	var b bytes.Buffer
	return muta.NewEasyStreamer("markdown.Markdown", func(fi *muta.FileInfo, chunk []byte) (*muta.FileInfo, []byte, error) {
		switch {
		case fi == nil:
			// If fi is nil, Markdown() is being asked to generate files.
			return generate()

		case filepath.Ext(fi.Name) != ".md":
			// If the file is not Markdown, pass it through untouched.
			return fi, chunk, nil

		case chunk == nil:
			// If chunk is nil, we're at the EOF for the incoming data for *fi
			return write(&b, fi, chunk)

		default:
			// If chunk isn't nil, buffer the data
			return buffer(&b, chunk)
		}
	})
}
<|endoftext|>


<commit_before>package other<commit_msg>Remove old example file<commit_after><|endoftext|>


<commit_before>package mastodon

import (
	"encoding/json"
	"net/http"
	"net/url"
	"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
}

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            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"`
	} `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) 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)
	//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
}

// 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
}
<commit_msg>Add GetAccount<commit_after>package mastodon

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"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
}

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"`
}

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
}

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) 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)
	//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
}

// 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
}
<|endoftext|>


<commit_before>package muts

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
)

var execCommand = exec.Command

// Call runs an operating system command composed of the parameters given.
// If only one parameter is given then interpret that as a single command line.
// Block until the command has finished.
// Calls Abort if the call failed.
func Call(params ...interface{}) int {
	r := Exec(NewExecOptions(params...))
	if !r.Ok() {
		Abort(r.Error)
	}
	return r.PID
}

// CallReturn runs an operating system command composed of the parameters given.
// If only one parameter is given then interpret that as a single command line.
// Block until the command has finished.
// Returns what is written to stdout or to stderror if an error was detected.
func CallReturn(params ...interface{}) (string, error) {
	errBuffer := new(bytes.Buffer)
	outBuffer := new(bytes.Buffer)
	opts := NewExecOptions(params...)
	opts.Stderr(errBuffer)
	opts.Stdout(outBuffer)
	r := Exec(opts)
	if !r.Ok() {
		return outBuffer.String() + "\n" + errBuffer.String(), errors.New(r.Error)
	}
	return outBuffer.String(), nil
}

// CallBackground runs an operating system command composed of the parameters given.
// If only one parameter is given then interpret that as a single command line.
// The output (stderr and stdout) of the result will be empty.
// Does not block ; this function returns immediately. Use the PID value of the result to handle the process.
func CallBackground(params ...interface{}) ExecResult {
	return Exec(NewExecOptions(params...).Wait(false))
}

// ExecResult holds the result of a Call.
type ExecResult struct {
	PID    int
	Error  string
	Stderr string
	Stdout string
}

// Ok returns whether the call was succesful. Only valid is the call was not run in the background.
func (r ExecResult) Ok() bool {
	return r.PID != 0
}

// ExecOptions is a parameter object for the Exec call
type ExecOptions struct {
	parameters []interface{}
	wait       bool
	force      bool
	output     io.Writer
	input      io.Reader
	errput     io.Writer
}

// Wait sets whether the call should wait for the command to complete. Default is true.
func (o *ExecOptions) Wait(w bool) *ExecOptions {
	o.wait = w
	return o
}

// Force determines if the program should continue when the cmd fails. If false the application will abort and defers
// are fired. Default is false.
func (o *ExecOptions) Force(f bool) *ExecOptions {
	o.force = f
	return o
}

// When Silent is set to true stdout and stderr will be discarded. Otherwise it is streamed as usual. Default is false.
// especially useful combined with force when you know you want re-runnable commands.
func (o *ExecOptions) Silent(s bool) *ExecOptions {
	if s {
		o.output = ioutil.Discard
		o.errput = ioutil.Discard
	}
	return o
}

// Stdout sets the writer for capturing the output produced by the command.
func (o *ExecOptions) Stdout(w io.Writer) *ExecOptions {
	o.output = w
	return o
}

// Stderr sets the writer for capturing the output produced by the command.
func (o *ExecOptions) Stderr(w io.Writer) *ExecOptions {
	o.errput = w
	return o
}

// Stderr sets the reader for accepting the input needed by the command.
func (o *ExecOptions) Stdin(r io.Reader) *ExecOptions {
	o.input = r
	return o
}

// Parameters sets the command and arguments. Can be a combination of values that are Stringers.
func (o *ExecOptions) Parameters(params ...interface{}) *ExecOptions {
	o.parameters = params
	return o
}

// NewExecOptions returns a new ExecOptions to be used in a Exec function call.
func NewExecOptions(params ...interface{}) *ExecOptions {
	return &ExecOptions{
		parameters: params,
		wait:       true,
		force:      false,
		output:     os.Stdout,
		input:      os.Stdin,
		errput:     os.Stderr,
	}
}

// Exec runs a shell command with parameters and settings from CallOptions
// Returns the process ID if not waiting and then 0 means there is a problem.
func Exec(options *ExecOptions) ExecResult {
	args := make([]string, len(options.parameters))
	for i, each := range options.parameters {
		args[i] = paramAsString(each)
	}
	if len(args) == 1 { // tokenize
		args = strings.Split(args[0], " ")
	}
	cmdline := strings.Join(args, " ")
	log.Println("[sh -c]", cmdline)
	cmd := execCommand("sh", "-c", cmdline)
	cmd.Stdin = options.input

	cmd.Stdout = options.output
	cmd.Stderr = options.errput
	if options.wait {
		if err := cmd.Run(); err != nil && !options.force {
			return ExecResult{
				Error: err.Error(),
			}
		}
	} else {
		if err := cmd.Start(); err != nil {
			return ExecResult{
				Error: err.Error(),
			}
		}
	}
	if cmd.Process == nil {
		// if we don't know why
		return ExecResult{}
	}
	return ExecResult{PID: cmd.Process.Pid}
}

func paramAsString(p interface{}) string {
	if s, ok := p.(string); ok {
		return s
	}
	if s, ok := p.(fmt.Stringer); ok {
		return s.String()
	}
	return fmt.Sprintf("%v", p)
}
<commit_msg>remove trailing newlines from CallReturn<commit_after>package muts

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
)

var execCommand = exec.Command

// Call runs an operating system command composed of the parameters given.
// If only one parameter is given then interpret that as a single command line.
// Block until the command has finished.
// Calls Abort if the call failed.
func Call(params ...interface{}) int {
	r := Exec(NewExecOptions(params...))
	if !r.Ok() {
		Abort(r.Error)
	}
	return r.PID
}

// CallReturn runs an operating system command composed of the parameters given.
// If only one parameter is given then interpret that as a single command line.
// Block until the command has finished.
// Returns what is written to stdout or to stderror if an error was detected.
// The last newline(s) (if any) are stripped.
func CallReturn(params ...interface{}) (string, error) {
	errBuffer := new(bytes.Buffer)
	outBuffer := new(bytes.Buffer)
	opts := NewExecOptions(params...)
	opts.Stderr(errBuffer)
	opts.Stdout(outBuffer)
	r := Exec(opts)
	if !r.Ok() {
		return outBuffer.String() + "\n" + errBuffer.String(), errors.New(r.Error)
	}
	return strings.TrimRight(outBuffer.String(), "\n"), nil
}

// CallBackground runs an operating system command composed of the parameters given.
// If only one parameter is given then interpret that as a single command line.
// The output (stderr and stdout) of the result will be empty.
// Does not block ; this function returns immediately. Use the PID value of the result to handle the process.
func CallBackground(params ...interface{}) ExecResult {
	return Exec(NewExecOptions(params...).Wait(false))
}

// ExecResult holds the result of a Call.
type ExecResult struct {
	PID    int
	Error  string
	Stderr string
	Stdout string
}

// Ok returns whether the call was succesful. Only valid is the call was not run in the background.
func (r ExecResult) Ok() bool {
	return r.PID != 0
}

// ExecOptions is a parameter object for the Exec call
type ExecOptions struct {
	parameters []interface{}
	wait       bool
	force      bool
	output     io.Writer
	input      io.Reader
	errput     io.Writer
}

// Wait sets whether the call should wait for the command to complete. Default is true.
func (o *ExecOptions) Wait(w bool) *ExecOptions {
	o.wait = w
	return o
}

// Force determines if the program should continue when the cmd fails. If false the application will abort and defers
// are fired. Default is false.
func (o *ExecOptions) Force(f bool) *ExecOptions {
	o.force = f
	return o
}

// When Silent is set to true stdout and stderr will be discarded. Otherwise it is streamed as usual. Default is false.
// especially useful combined with force when you know you want re-runnable commands.
func (o *ExecOptions) Silent(s bool) *ExecOptions {
	if s {
		o.output = ioutil.Discard
		o.errput = ioutil.Discard
	}
	return o
}

// Stdout sets the writer for capturing the output produced by the command.
func (o *ExecOptions) Stdout(w io.Writer) *ExecOptions {
	o.output = w
	return o
}

// Stderr sets the writer for capturing the output produced by the command.
func (o *ExecOptions) Stderr(w io.Writer) *ExecOptions {
	o.errput = w
	return o
}

// Stderr sets the reader for accepting the input needed by the command.
func (o *ExecOptions) Stdin(r io.Reader) *ExecOptions {
	o.input = r
	return o
}

// Parameters sets the command and arguments. Can be a combination of values that are Stringers.
func (o *ExecOptions) Parameters(params ...interface{}) *ExecOptions {
	o.parameters = params
	return o
}

// NewExecOptions returns a new ExecOptions to be used in a Exec function call.
func NewExecOptions(params ...interface{}) *ExecOptions {
	return &ExecOptions{
		parameters: params,
		wait:       true,
		force:      false,
		output:     os.Stdout,
		input:      os.Stdin,
		errput:     os.Stderr,
	}
}

// Exec runs a shell command with parameters and settings from CallOptions
// Returns the process ID if not waiting and then 0 means there is a problem.
func Exec(options *ExecOptions) ExecResult {
	args := make([]string, len(options.parameters))
	for i, each := range options.parameters {
		args[i] = paramAsString(each)
	}
	if len(args) == 1 { // tokenize
		args = strings.Split(args[0], " ")
	}
	cmdline := strings.Join(args, " ")
	log.Println("[sh -c]", cmdline)
	cmd := execCommand("sh", "-c", cmdline)
	cmd.Stdin = options.input

	cmd.Stdout = options.output
	cmd.Stderr = options.errput
	if options.wait {
		if err := cmd.Run(); err != nil && !options.force {
			return ExecResult{
				Error: err.Error(),
			}
		}
	} else {
		if err := cmd.Start(); err != nil {
			return ExecResult{
				Error: err.Error(),
			}
		}
	}
	if cmd.Process == nil {
		// if we don't know why
		return ExecResult{}
	}
	return ExecResult{PID: cmd.Process.Pid}
}

func paramAsString(p interface{}) string {
	if s, ok := p.(string); ok {
		return s
	}
	if s, ok := p.(fmt.Stringer); ok {
		return s.String()
	}
	return fmt.Sprintf("%v", p)
}
<|endoftext|>


<commit_before>// Copyright 2017 The go-rollbar 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 rollbar

import (
	"golang.org/x/net/context"
)

type Call interface {
	Custom(map[string]interface{}) Call
	UUID(string) Call
	Do(context.Context) error
}

type callOption struct {
	err    error
	custom map[string]interface{}
	id     string
}

type DebugCall struct {
	client *httpClient
	callOption
}

// Debug sends the error to rollbar with debug level.
func (c *Client) Debug(err error) Call {
	var call DebugCall
	call.client = c.debugClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *DebugCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *DebugCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *DebugCall) Do(ctx context.Context) error {
	payload := c.client.payload(DebugLevel, c.err)
	payload.Data.Custom = c.custom
	payload.Data.UUID = c.id
	return c.client.post(ctx, payload)
}

type InfoCall struct {
	client *httpClient
	callOption
}

// Info sends the error to rollbar with info level.
func (c *Client) Info(err error) Call {
	var call InfoCall
	call.client = c.infoClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *InfoCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *InfoCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *InfoCall) Do(ctx context.Context) error {
	payload := c.client.payload(InfoLevel, c.err)
	payload.Data.Custom = c.custom
	payload.Data.UUID = c.id
	return c.client.post(ctx, payload)
}

type ErrorCall struct {
	client *httpClient
	callOption
}

// Error sends the error to rollbar with error level.
func (c *Client) Error(err error) Call {
	var call ErrorCall
	call.client = c.errorClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *ErrorCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *ErrorCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *ErrorCall) Do(ctx context.Context) error {
	payload := c.client.payload(ErrorLevel, c.err)
	payload.Data.Custom = c.custom
	payload.Data.UUID = c.id
	return c.client.post(ctx, payload)
}

type WarnCall struct {
	client *httpClient
	callOption
}

// Warn sends the error to rollbar with warning level.
func (c *Client) Warn(err error) Call {
	var call WarnCall
	call.client = c.warnClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *WarnCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *WarnCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *WarnCall) Do(ctx context.Context) error {
	payload := c.client.payload(WarnLevel, c.err)
	payload.Data.Custom = c.custom
	payload.Data.UUID = c.id
	return c.client.post(ctx, payload)
}

type CriticalCall struct {
	client *httpClient
	callOption
}

// Critical sends the error to rollbar with critical level.
func (c *Client) Critical(err error) Call {
	var call CriticalCall
	call.client = c.criticalClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *CriticalCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *CriticalCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *CriticalCall) Do(ctx context.Context) error {
	payload := c.client.payload(CriticalLevel, c.err)
	payload.Data.Custom = c.custom
	payload.Data.UUID = c.id
	return c.client.post(ctx, payload)
}
<commit_msg>call: refactor join payload data<commit_after>// Copyright 2017 The go-rollbar 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 rollbar

import (
	api "github.com/zchee/go-rollbar/api/v1"
	"golang.org/x/net/context"
)

type Call interface {
	Custom(map[string]interface{}) Call
	UUID(string) Call
	Do(context.Context) error
}

type callOption struct {
	err    error
	custom map[string]interface{}
	id     string
}

func joinPayload(payload *api.Payload, opt callOption) {
	if opt.custom != nil {
		payload.Data.Custom = opt.custom
	}
	if opt.id != "" {
		payload.Data.UUID = opt.id
	}
}

type DebugCall struct {
	client *httpClient
	callOption
}

// Debug sends the error to rollbar with debug level.
func (c *Client) Debug(err error) Call {
	var call DebugCall
	call.client = c.debugClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *DebugCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *DebugCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *DebugCall) Do(ctx context.Context) error {
	payload := c.client.payload(DebugLevel, c.err)
	joinPayload(payload, c.callOption)
	return c.client.post(ctx, payload)
}

type InfoCall struct {
	client *httpClient
	callOption
}

// Info sends the error to rollbar with info level.
func (c *Client) Info(err error) Call {
	var call InfoCall
	call.client = c.infoClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *InfoCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *InfoCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *InfoCall) Do(ctx context.Context) error {
	payload := c.client.payload(InfoLevel, c.err)
	joinPayload(payload, c.callOption)
	return c.client.post(ctx, payload)
}

type ErrorCall struct {
	client *httpClient
	callOption
}

// Error sends the error to rollbar with error level.
func (c *Client) Error(err error) Call {
	var call ErrorCall
	call.client = c.errorClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *ErrorCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *ErrorCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *ErrorCall) Do(ctx context.Context) error {
	payload := c.client.payload(ErrorLevel, c.err)
	joinPayload(payload, c.callOption)
	return c.client.post(ctx, payload)
}

type WarnCall struct {
	client *httpClient
	callOption
}

// Warn sends the error to rollbar with warning level.
func (c *Client) Warn(err error) Call {
	var call WarnCall
	call.client = c.warnClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *WarnCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *WarnCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *WarnCall) Do(ctx context.Context) error {
	payload := c.client.payload(WarnLevel, c.err)
	joinPayload(payload, c.callOption)
	return c.client.post(ctx, payload)
}

type CriticalCall struct {
	client *httpClient
	callOption
}

// Critical sends the error to rollbar with critical level.
func (c *Client) Critical(err error) Call {
	var call CriticalCall
	call.client = c.criticalClient
	call.err = err
	return &call
}

// Custom is any arbitrary metadata you want to send. "custom" itself should be an object.
func (c *CriticalCall) Custom(custom map[string]interface{}) Call {
	c.custom = custom
	return c
}

// UUID a string, up to 36 characters, that uniquely identifies this occurrence.
// While it can now be any latin1 string, this may change to be a 16 byte field in the future.
// We recommend using a UUID4 (16 random bytes).
// The UUID space is unique to each project, and can be used to look up an occurrence later.
// It is also used to detect duplicate requests. If you send the same UUID in two payloads, the second
// one will be discarded.
// While optional, it is recommended that all clients generate and provide this field.
func (c *CriticalCall) UUID(id string) Call {
	c.id = id
	return c
}

func (c *CriticalCall) Do(ctx context.Context) error {
	payload := c.client.payload(CriticalLevel, c.err)
	joinPayload(payload, c.callOption)
	return c.client.post(ctx, payload)
}
<|endoftext|>


<commit_before>package puppetdb

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Client struct {
	BaseURL    string
	PublicKey  string
	SecretKey  string
	httpClient *http.Client
	verbose    bool
}

type EventCountJson struct {
	SubjectType string            `json:"subject-type"`
	Subject     map[string]string `json:"subject"`
	Failure     int64             `json:"failures"`
	Successes   int64             `json:"successes"`
	Noops       int64             `json:"noops"`
	Skips       int64             `json:"skips"`
}

type EventJson struct {
	CertName          string `json:"certname"`
	OldValue          string `json:"old-value"`
	Property          string `json:"message"`
	Timestamp         string `json:"timestamp"`
	ResourceType      string `json:"resource-typ"`
	ResourceTitle     string `json:"resource-title"`
	NewValue          string `json:"new-value"`
	Message           string `json:"message"`
	Report            string `json:"report"`
	Status            string `json:"status"`
	File              string `json:"file"`
	ContainmentPath   string `json:"containment-path"`
	ContainmentClass  string `json:"containing-class"`
	RunStartTime      string `json:"run-start-time"`
	RunEndTime        string `json:"run-end-time"`
	ReportReceiveTime string `json:"report-receive-time"`
}

type FactJson struct {
	CertName string `json:"certname"`
	Name     string `json:"name"`
	Value    string `json:"value"`
}

type NodeJson struct {
	Name             string `json:"name"`
	Deactivated      string `json:"deactivated"`
	CatalogTimestamp string `json:"catalog_timestamp"`
	FactsTimestamp   string `json:"facts_timestamp"`
	ReportTimestamp  string `json:"report_timestamp"`
}

type PuppetdbVersion struct {
	Version string `json:"version"`
}

type ReportJson struct {
	CertName             string `json:"certname"`
	PuppetVersion        string `json:"puppet-version"`
	Value                string `json:"value"`
	Hash                 string `json:"hash"`
	ReportFormat         int64  `json:"report-format"`
	ConfigurationVersion string `json:"configuration-version"`
	TransactionUUID      string `json:"transaction-uuid"`
	StartTime            string `json:"start-time"`
	EndTime              string `json:"end-time"`
	ReceiveTime          string `json:"receive-time"`
}

type ValueMetricJson struct {
	Value float64
}

func NewClient(baseUrl string, verbose bool) *Client {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr}
	return &Client{baseUrl, "", "", client, verbose}
}

func NewClientWithTimeout(baseUrl string, verbose bool, timeout int) *Client {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr, Timeout: time.Duration(timeout) * time.Second}
	return &Client{baseUrl, "", "", client, verbose}
}

func (c *Client) Get(v interface{}, path string, params map[string]string) error {
	pathAndParams := path
	//TODO: Improve this
	if params != nil && len(params) > 0 {
		if !strings.Contains(path, "?") {
			pathAndParams += "?"
		}
		for k, v := range params {
			pathAndParams += fmt.Sprintf("%s=%s&", k, url.QueryEscape(v))
		}
	}
	resp, err := c.httpGet(pathAndParams)
	if err != nil {
		log.Print(err)
		return err
	}
	defer resp.Body.Close()
	if err != nil {
		log.Print(err)
		return err
	}
	json.NewDecoder(resp.Body).Decode(&v)
	return err
}

func (c *Client) Nodes() ([]NodeJson, error) {
	ret := []NodeJson{}
	err := c.Get(&ret, "nodes", nil)
	return ret, err
}

func (c *Client) FactNames() ([]string, error) {
	ret := []string{}
	err := c.Get(&ret, "fact-names", nil)
	return ret, err
}

func (c *Client) NodeFacts(node string) ([]FactJson, error) {
	url := fmt.Sprintf("nodes/%s/facts", node)
	ret := []FactJson{}
	err := c.Get(&ret, url, nil)
	return ret, err
}

func (c *Client) FactPerNode(fact string) ([]FactJson, error) {
	url := fmt.Sprintf("facts/%s", fact)
	ret := []FactJson{}
	err := c.Get(&ret, url, nil)
	return ret, err
}

func (c *Client) EventCounts(query string, summarizeBy string, extraParams map[string]string) ([]EventCountJson, error) {
	path := "event-counts"
	ret := []EventCountJson{}
	params := mergeParam("query", query, extraParams)
	params = mergeParam("summarize-by", summarizeBy, params)
	err := c.Get(&ret, path, params)
	return ret, err
}

func (c *Client) Events(query string, extraParams map[string]string) ([]EventJson, error) {
	path := "events"
	ret := []EventJson{}
	params := mergeParam("query", query, extraParams)
	err := c.Get(&ret, path, params)
	return ret, err
}

func (c *Client) Metric(v interface{}, metric string) error {
	url := fmt.Sprintf("metrics/mbean/%s", metric)
	err := c.Get(&v, url, nil)
	return err
}

func (c *Client) MetricResourcesPerNode() (result float64, err error) {
	ret := ValueMetricJson{}
	return ret.Value, c.Metric(&ret, "com.puppetlabs.puppetdb.query.population:type=default,name=avg-resources-per-node")
}

func (c *Client) MetricNumResources() (result float64, err error) {
	ret := ValueMetricJson{}
	return ret.Value, c.Metric(&ret, "com.puppetlabs.puppetdb.query.population:type=default,name=num-resources")
}

func (c *Client) MetricNumNodes() (result float64, err error) {
	ret := ValueMetricJson{}
	return ret.Value, c.Metric(&ret, "com.puppetlabs.puppetdb.query.population:type=default,name=num-nodes")
}

func (c *Client) Reports(query string, extraParams map[string]string) ([]ReportJson, error) {
	path := "reports"
	ret := []ReportJson{}
	params := mergeParam("query", query, extraParams)
	err := c.Get(&ret, path, params)
	return ret, err
}

func (c *Client) PuppetdbVersion() (PuppetdbVersion, error) {
	path := "version"
	ret := PuppetdbVersion{}
	err := c.Get(&ret, path, nil)
	return ret, err
}

func QueryToJson(query interface{}) (result string, err error) {
	resultBytes, err := json.Marshal(query)
	jsonQuery := string(resultBytes[:])
	return jsonQuery, err
}

func mergeParam(paramName string, paramValue string, params map[string]string) map[string]string {
	resultParams := make(map[string]string)
	if paramValue != "" {
		resultParams[paramName] = paramValue
	}
	if params != nil && len(params) > 0 {
		for k, v := range params {
			resultParams[k] = v
		}
	}
	return resultParams
}

func (c *Client) httpGet(endpoint string) (resp *http.Response, err error) {
	base := strings.TrimRight(c.BaseURL, "/")
	url := fmt.Sprintf("%s/v4/%s", base, endpoint)
	if c.verbose == true {
		log.Printf(url)
	}
	return c.httpClient.Get(url)
}
<commit_msg>Add support for resources<commit_after>package puppetdb

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Client struct {
	BaseURL    string
	PublicKey  string
	SecretKey  string
	httpClient *http.Client
	verbose    bool
}

type EventCountJson struct {
	SubjectType string            `json:"subject-type"`
	Subject     map[string]string `json:"subject"`
	Failure     int64             `json:"failures"`
	Successes   int64             `json:"successes"`
	Noops       int64             `json:"noops"`
	Skips       int64             `json:"skips"`
}

type EventJson struct {
	CertName          string `json:"certname"`
	OldValue          string `json:"old-value"`
	Property          string `json:"message"`
	Timestamp         string `json:"timestamp"`
	ResourceType      string `json:"resource-typ"`
	ResourceTitle     string `json:"resource-title"`
	NewValue          string `json:"new-value"`
	Message           string `json:"message"`
	Report            string `json:"report"`
	Status            string `json:"status"`
	File              string `json:"file"`
	ContainmentPath   string `json:"containment-path"`
	ContainmentClass  string `json:"containing-class"`
	RunStartTime      string `json:"run-start-time"`
	RunEndTime        string `json:"run-end-time"`
	ReportReceiveTime string `json:"report-receive-time"`
}

type FactJson struct {
	CertName string `json:"certname"`
	Name     string `json:"name"`
	Value    string `json:"value"`
}

type NodeJson struct {
	Name             string `json:"name"`
	Deactivated      string `json:"deactivated"`
	CatalogTimestamp string `json:"catalog_timestamp"`
	FactsTimestamp   string `json:"facts_timestamp"`
	ReportTimestamp  string `json:"report_timestamp"`
}

type PuppetdbVersion struct {
	Version string `json:"version"`
}

type ReportJson struct {
	CertName             string `json:"certname"`
	PuppetVersion        string `json:"puppet-version"`
	Value                string `json:"value"`
	Hash                 string `json:"hash"`
	ReportFormat         int64  `json:"report-format"`
	ConfigurationVersion string `json:"configuration-version"`
	TransactionUUID      string `json:"transaction-uuid"`
	StartTime            string `json:"start-time"`
	EndTime              string `json:"end-time"`
	ReceiveTime          string `json:"receive-time"`
}

//Resource contains information about a puppet resource.
type Resource struct {
	Paramaters map[string]interface{} `json:"parameters"`
	Line       int                    `json:"line,omitempty"`
	Exported   bool                   `json:"exported,omitempty"`
	Tags       []string               `json:"tags,omitempty"`
	Title      string                 `json:"title,omitempty"`
	Type       string                 `json:"type,omitempty"`
	Resource   string                 `json:"resource,omitempty"`
	Certname   string                 `json:"certname,omitempty"`
}

type ValueMetricJson struct {
	Value float64
}

func NewClient(baseUrl string, verbose bool) *Client {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr}
	return &Client{baseUrl, "", "", client, verbose}
}

func NewClientWithTimeout(baseUrl string, verbose bool, timeout int) *Client {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr, Timeout: time.Duration(timeout) * time.Second}
	return &Client{baseUrl, "", "", client, verbose}
}

func (c *Client) Get(v interface{}, path string, params map[string]string) error {
	pathAndParams := path
	//TODO: Improve this
	if params != nil && len(params) > 0 {
		if !strings.Contains(path, "?") {
			pathAndParams += "?"
		}
		for k, v := range params {
			pathAndParams += fmt.Sprintf("%s=%s&", k, url.QueryEscape(v))
		}
	}
	resp, err := c.httpGet(pathAndParams)
	if err != nil {
		log.Print(err)
		return err
	}
	defer resp.Body.Close()
	if err != nil {
		log.Print(err)
		return err
	}
	json.NewDecoder(resp.Body).Decode(&v)
	return err
}

func (c *Client) Nodes() ([]NodeJson, error) {
	ret := []NodeJson{}
	err := c.Get(&ret, "nodes", nil)
	return ret, err
}

func (c *Client) FactNames() ([]string, error) {
	ret := []string{}
	err := c.Get(&ret, "fact-names", nil)
	return ret, err
}

func (c *Client) NodeFacts(node string) ([]FactJson, error) {
	url := fmt.Sprintf("nodes/%s/facts", node)
	ret := []FactJson{}
	err := c.Get(&ret, url, nil)
	return ret, err
}

func (c *Client) FactPerNode(fact string) ([]FactJson, error) {
	url := fmt.Sprintf("facts/%s", fact)
	ret := []FactJson{}
	err := c.Get(&ret, url, nil)
	return ret, err
}

func (c *Client) EventCounts(query string, summarizeBy string, extraParams map[string]string) ([]EventCountJson, error) {
	path := "event-counts"
	ret := []EventCountJson{}
	params := mergeParam("query", query, extraParams)
	params = mergeParam("summarize-by", summarizeBy, params)
	err := c.Get(&ret, path, params)
	return ret, err
}

func (c *Client) Events(query string, extraParams map[string]string) ([]EventJson, error) {
	path := "events"
	ret := []EventJson{}
	params := mergeParam("query", query, extraParams)
	err := c.Get(&ret, path, params)
	return ret, err
}

//Resources will fetch resources from /resources/ in the puppetdb api
func (c *Client) Resources(query string, extraParams map[string]string) ([]Resource, error) {
	in := []Resource{}
	params := mergeParam("query", query, extraParams)
	err := c.Get(&in, "resources", params)
	return in, err
}

func (c *Client) Metric(v interface{}, metric string) error {
	url := fmt.Sprintf("metrics/mbean/%s", metric)
	err := c.Get(&v, url, nil)
	return err
}

func (c *Client) MetricResourcesPerNode() (result float64, err error) {
	ret := ValueMetricJson{}
	return ret.Value, c.Metric(&ret, "com.puppetlabs.puppetdb.query.population:type=default,name=avg-resources-per-node")
}

func (c *Client) MetricNumResources() (result float64, err error) {
	ret := ValueMetricJson{}
	return ret.Value, c.Metric(&ret, "com.puppetlabs.puppetdb.query.population:type=default,name=num-resources")
}

func (c *Client) MetricNumNodes() (result float64, err error) {
	ret := ValueMetricJson{}
	return ret.Value, c.Metric(&ret, "com.puppetlabs.puppetdb.query.population:type=default,name=num-nodes")
}

func (c *Client) Reports(query string, extraParams map[string]string) ([]ReportJson, error) {
	path := "reports"
	ret := []ReportJson{}
	params := mergeParam("query", query, extraParams)
	err := c.Get(&ret, path, params)
	return ret, err
}

func (c *Client) PuppetdbVersion() (PuppetdbVersion, error) {
	path := "version"
	ret := PuppetdbVersion{}
	err := c.Get(&ret, path, nil)
	return ret, err
}

func QueryToJson(query interface{}) (result string, err error) {
	resultBytes, err := json.Marshal(query)
	jsonQuery := string(resultBytes[:])
	return jsonQuery, err
}

func mergeParam(paramName string, paramValue string, params map[string]string) map[string]string {
	resultParams := make(map[string]string)
	if paramValue != "" {
		resultParams[paramName] = paramValue
	}
	if params != nil && len(params) > 0 {
		for k, v := range params {
			resultParams[k] = v
		}
	}
	return resultParams
}

func (c *Client) httpGet(endpoint string) (resp *http.Response, err error) {
	base := strings.TrimRight(c.BaseURL, "/")
	url := fmt.Sprintf("%s/v4/%s", base, endpoint)
	if c.verbose == true {
		log.Printf(url)
	}
	return c.httpClient.Get(url)
}
<|endoftext|>


<commit_before>package sdees

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"unicode/utf8"
)

func SummarizeEntries(texts []string, textsBranch []string) string {
	var summarized []string
	for i, text := range texts {
		dateInfo := strings.TrimSpace(strings.Split(text, " -==- ")[0])
		dateInfo = strings.Join(strings.Split(dateInfo, " ")[:5], " ")
		text = strings.Join(strings.Split(text, "\n")[1:], " ")
		words := strings.Split(text, " ")
		sentence := ""
		numWords := 1
		for {
			numWords++
			sentence = strings.Join(words[0:numWords], " ")
			if utf8.RuneCountInString(strings.TrimSpace(sentence)) > 80 || numWords >= len(words) {
				sentence = strings.Join(words[0:numWords-1], " ")
				break
			}
		}
		summarized = append(summarized,
			fmt.Sprintf("%s - %s (%s words):\n  %s", textsBranch[i], dateInfo, NumberToString(len(words), ','), strings.TrimSpace(sentence)))
	}
	return strings.Join(summarized, "\n")
}

func NumberToString(n int, sep rune) string {

	s := strconv.Itoa(n)

	startOffset := 0
	var buff bytes.Buffer

	if n < 0 {
		startOffset = 1
		buff.WriteByte('-')
	}

	l := len(s)

	commaIndex := 3 - ((l - startOffset) % 3)

	if commaIndex == 3 {
		commaIndex = 0
	}

	for i := startOffset; i < l; i++ {

		if commaIndex == 3 {
			buff.WriteRune(sep)
			commaIndex = 0
		}
		commaIndex++

		buff.WriteByte(s[i])
	}

	return buff.String()
}
<commit_msg>HashIDToString for summarizer<commit_after>package sdees

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"unicode/utf8"
)

func SummarizeEntries(texts []string, textsBranch []string) string {
	var summarized []string
	for i, text := range texts {
		dateInfo := strings.TrimSpace(strings.Split(text, " -==- ")[0])
		dateInfo = strings.Join(strings.Split(dateInfo, " ")[:5], " ")
		text = strings.Join(strings.Split(text, "\n")[1:], " ")
		words := strings.Split(text, " ")
		sentence := ""
		numWords := 1
		for {
			numWords++
			sentence = strings.Join(words[0:numWords], " ")
			if utf8.RuneCountInString(strings.TrimSpace(sentence)) > 80 || numWords >= len(words) {
				sentence = strings.Join(words[0:numWords-1], " ")
				break
			}
		}
		summarized = append(summarized,
				    fmt.Sprintf("%s - %s (%s words):\n  %s", HashIDToString(textsBranch[i]), dateInfo, NumberToString(len(words), ','), strings.TrimSpace(sentence)))
	}
	return strings.Join(summarized, "\n")
}

func NumberToString(n int, sep rune) string {

	s := strconv.Itoa(n)

	startOffset := 0
	var buff bytes.Buffer

	if n < 0 {
		startOffset = 1
		buff.WriteByte('-')
	}

	l := len(s)

	commaIndex := 3 - ((l - startOffset) % 3)

	if commaIndex == 3 {
		commaIndex = 0
	}

	for i := startOffset; i < l; i++ {

		if commaIndex == 3 {
			buff.WriteRune(sep)
			commaIndex = 0
		}
		commaIndex++

		buff.WriteByte(s[i])
	}

	return buff.String()
}
<|endoftext|>


<commit_before>package renderweb

import (
	"net/http"

	"github.com/rs/xhandler"
	"github.com/rs/xmux"
	"golang.org/x/net/context"

	"tower.pro/renderer/components"
	"tower.pro/renderer/middlewares"
)

// Handler - Web route handler.
type Handler struct {
	Component   *components.Component     `json:"component,omitempty" yaml:"component,omitempty"`
	Middlewares []*middlewares.Middleware `json:"middlewares,omitempty" yaml:"middlewares,omitempty"`
}

// Construct - Constructs http handler.
func (h *Handler) Construct(opts ...Option) (xhandler.HandlerC, error) {
	// Request initialization middleware
	opts = append(opts, WithMiddleware(ToMiddleware(initMiddleware)))

	// Set component-setting middleware with handler component
	opts = append(opts, WithComponentSetter(ComponentMiddleware(h.Component)))

	// Construct handler middlewares
	for _, md := range h.Middlewares {
		middleware, err := middlewares.Construct(md)
		if err != nil {
			return nil, err
		}
		opts = append(opts, WithMiddleware(middleware))
	}

	return New(opts...), nil
}

func initMiddleware(ctx context.Context, w http.ResponseWriter, r *http.Request, next xhandler.HandlerC) {
	ctx = NewRequestContext(ctx, r)
	ctx = components.WithTemplateKey(ctx, "request", r)
	ctx = components.WithTemplateKey(ctx, "params", xmux.Params(ctx))
	next.ServeHTTPC(ctx, w, r)
}
<commit_msg>renderweb: middlewares tracing<commit_after>package renderweb

import (
	"net/http"

	"github.com/rs/xhandler"
	"github.com/rs/xmux"
	"golang.org/x/net/context"
	"golang.org/x/net/trace"

	"tower.pro/renderer/components"
	"tower.pro/renderer/middlewares"
)

// Handler - Web route handler.
type Handler struct {
	Component   *components.Component     `json:"component,omitempty" yaml:"component,omitempty"`
	Middlewares []*middlewares.Middleware `json:"middlewares,omitempty" yaml:"middlewares,omitempty"`
}

// Construct - Constructs http handler.
func (h *Handler) Construct(opts ...Option) (xhandler.HandlerC, error) {
	// Request initialization middleware
	opts = append(opts, WithMiddleware(initMiddleware))

	// Set component-setting middleware with handler component
	opts = append(opts, WithComponentSetter(ComponentMiddleware(h.Component)))

	// Check if tracing is enabled
	tracing := tracingEnabled(opts...)

	// Construct handler middlewares
	for _, md := range h.Middlewares {
		middleware, err := middlewares.Construct(md)
		if err != nil {
			return nil, err
		}
		if tracing {
			middleware = tracingMiddleware(md, middleware)
		}
		opts = append(opts, WithMiddleware(middleware))
	}

	return New(opts...), nil
}

var initMiddleware = ToMiddleware(func(ctx context.Context, w http.ResponseWriter, r *http.Request, next xhandler.HandlerC) {
	ctx = NewRequestContext(ctx, r)
	ctx = components.WithTemplateKey(ctx, "request", r)
	ctx = components.WithTemplateKey(ctx, "params", xmux.Params(ctx))
	next.ServeHTTPC(ctx, w, r)
})

// tracingMiddleware - Tracing for middlewares.
func tracingMiddleware(md *middlewares.Middleware, handler middlewares.Handler) middlewares.Handler {
	return func(next xhandler.HandlerC) xhandler.HandlerC {
		h := handler(next)
		return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
			tr, _ := trace.FromContext(ctx)
			tr.LazyPrintf("%s", md.Name)
			h.ServeHTTPC(ctx, w, r)
		})
	}
}

func tracingEnabled(opts ...Option) bool {
	o := new(webOptions)
	for _, opt := range opts {
		opt(o)
	}
	return o.tracing
}
<|endoftext|>


<commit_before>// Copyright 2016 AlexStocks(https://github.com/AlexStocks).
// All rights reserved.  Use of this source code is
// governed by a BSD-style license.
package sync

// import (
// 	"sync/atomic"
// )
//
// type TryLock struct {
// 	lock int32
// }
//
// func (this *TryLock)Lock() bool {
// 	return atomic.CompareAndSwapInt32(&(this.lock), 0, 1)
// }
//
// func (this *TryLock)Unlock() {
//	atomic.StoreInt32(&(this.lock), 0)
// }

type TryLock struct {
	lock chan empty
}

func NewTryLock() *TryLock {
	return &TryLock{lock: make(chan empty, 1)}
}

func (this *TryLock) Lock() {
	this.lock <- empty{}
}

func (this *Semaphore) Trylock() bool {
	select {
	case this.lock <- empty{}:
		return true
	default:
		return false
	}
}

func (this *Semaphore) Unlock() {
	<-this.lock
}
<commit_msg>add trylock & semaphore & time<commit_after>// Copyright 2016 AlexStocks(https://github.com/AlexStocks).
// All rights reserved.  Use of this source code is
// governed by a BSD-style license.
package sync

// import (
// 	"sync/atomic"
// )
//
// type TryLock struct {
// 	lock int32
// }
//
// func (this *TryLock)Lock() bool {
// 	return atomic.CompareAndSwapInt32(&(this.lock), 0, 1)
// }
//
// func (this *TryLock)Unlock() {
//	atomic.StoreInt32(&(this.lock), 0)
// }

type TryLock struct {
	lock chan empty
}

func NewTryLock() *TryLock {
	return &TryLock{lock: make(chan empty, 1)}
}

func (this *TryLock) Lock() {
	this.lock <- empty{}
}

func (this *TryLock) Trylock() bool {
	select {
	case this.lock <- empty{}:
		return true
	default:
		return false
	}
}

func (this *TryLock) Unlock() {
	<-this.lock
}
<|endoftext|>


<commit_before>package cbqd

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
)

type AccessCreds struct {
	Dkey  string `json:"username"`
	Dpass string `json:"password"`
}

type Database struct {
	Ukey       AccessCreds
	Host, Port string
}

var (
	dbflag  = flag.String("db", "mysql", "Database type to dump.")
	csflag  = flag.String("cs", "aws", "S3 storage repository to use.")
	kvflag  = flag.Bool("kv", false, "Access vault to acquire secrets.")
	dhflag  = flag.String("dh", "127.0.0.1", "Host IP for the database to be backuped up.")
	dpflag  = flag.String("dp", "3306", "Database port for access.")
	vpflag  = flag.Bool("V", false, "Print the version number.")
	version = formattedVersion()
)

func (a AccessCreds) GetCreds(vbackend string, inout string, kvault bool) (AccessCreds, error) {
	un := inout + "_KEY"
	up := inout + "_PASS"
	ac := AccessCreds{}

	if kvault == false {
		ac.Dkey = os.Getenv(un)
		ac.Dpass = os.Getenv(up)
		if ac.Dkey == "" && ac.Dpass == "" {
			log.Fatalln(OS_ENVIRONMENT_UNSET)
		}
		return ac, nil
	}
	return ac, VAULT_CREDENTIAL_ERROR
}

func usage() {
	//
}

func init() {
	flag.Parse()
}

func Cbqd() {
	increds, err := new(AccessCreds).GetCreds(*dbflag, "CBQD_IN", *kvflag)
	if err != nil {
		log.Fatalln(err)
	}

	db := Database{increds, *dhflag, *dpflag}
	outcreds, err := new(AccessCreds).GetCreds(*csflag, "CBQD_OUT", *kvflag)
	if err != nil {
		log.Fatalln(err)
	}

	topdir, err := ioutil.TempDir("", "cbqd_state")
	if err != nil {
		log.Fatalln(err)
	}

	defer os.RemoveAll(topdir)
	tmpfhandle := filepath.Join(topdir, "tmpfile")

	bname, err := MYSQL{}.DBdump(db, tmpfhandle)
	if err != nil {
		log.Fatalln(err)
	}

	err0 := AWS{}.CloudSend(outcreds, bname, tmpfhandle)
	if err0 != nil {
		log.Fatalln(BACKUP_UPLOAD_ERROR)
	}

}
<commit_msg>update logging package<commit_after>package cbqd

import (
	"flag"
	"github.com/op/go-logging"
	"io/ioutil"
	"os"
	"path/filepath"
)

type AccessCreds struct {
	Dkey  string `json:"username"`
	Dpass string `json:"password"`
}

type Database struct {
	Ukey       AccessCreds
	Host, Port string
}

var (
	dbflag = flag.String("db", "mysql", "Database type to dump.")
	csflag = flag.String("cs", "aws", "S3 storage repository to use.")
	kvflag = flag.Bool("kv", false, "Access vault to acquire secrets.")
	dhflag = flag.String("dh", "127.0.0.1", "Host IP for the database to be backuped up.")
	dpflag = flag.String("dp", "3306", "Database port for access.")
	vpflag = flag.Bool("version", false, "Prints out the version number.")
	veflag = formattedVersion()
	lgform = logging.MustStringFormatter(`%{color}%{time:15:04:05.000} %{shortpkg} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`)
)

func (a AccessCreds) GetCreds(vbackend string, inout string, kvault bool) (AccessCreds, error) {
	un := inout + "_KEY"
	up := inout + "_PASS"
	ac := AccessCreds{}

	if kvault == false {
		ac.Dkey = os.Getenv(un)
		ac.Dpass = os.Getenv(up)
		if ac.Dkey == "" && ac.Dpass == "" {
			log.Fatalln(OS_ENVIRONMENT_UNSET)
		}
		return ac, nil
	}
	return ac, VAULT_CREDENTIAL_ERROR
}

func usage() {
	//
}

func init() {
	flag.Parse()
	bl1 := logging.NewLogBackend(os.Stderr, "", 0)
	blf := logging.NewBackendFormatter(bl1, lgform)
}

func Cbqd() {
	logging.SetBackend(bl1, blf)
	increds, err := new(AccessCreds).GetCreds(*dbflag, "CBQD_IN", *kvflag)
	if err != nil {
		log.Fatal(err)
	}

	db := Database{increds, *dhflag, *dpflag}
	outcreds, err := new(AccessCreds).GetCreds(*csflag, "CBQD_OUT", *kvflag)
	if err != nil {
		log.Fatal(err)
	}

	topdir, err := ioutil.TempDir("", "cbqd_state")
	if err != nil {
		log.Fatal(err)
	}

	defer os.RemoveAll(topdir)
	tmpfhandle := filepath.Join(topdir, "tmpfile")

	bname, err := MYSQL{}.DBdump(db, tmpfhandle)
	if err != nil {
		log.Fatal(err)
	}

	err0 := AWS{}.CloudSend(outcreds, bname, tmpfhandle)
	if err0 != nil {
		log.Fatal(BACKUP_UPLOAD_ERROR)
	}

}
<|endoftext|>