<commit_before>package sdm630

import (
	"fmt"
	"log"
	"regexp"
	"sort"
	"strings"

	MQTT "github.com/eclipse/paho.mqtt.golang"

	. "github.com/gonium/gosdm630/internal/meters"
)

const (
	version   = "3.0.1"
	nodeTopic = "meter"
)

type HomieRunner struct {
	*MqttClient
	rootTopic string
}

// Run MQTT client publisher
func (m *HomieRunner) Run(in QuerySnipChannel, rate int) {
	rateMap := make(RateMap)

	for {
		snip := <-in
		topic := fmt.Sprintf("%s/%s/%s/%s",
			m.rootTopic,
			m.DeviceTopic(snip.DeviceId),
			nodeTopic,
			strings.ToLower(snip.IEC61850.String()))

		if rateMap.Allowed(rate, topic) {
			message := fmt.Sprintf("%.3f", snip.Value)
			go m.Publish(topic, false, message)
		} else {
			if m.verbose {
				log.Printf("MQTT: skipped %s, rate to high", topic)
			}
		}
	}
}

// Register subcribes GoSDM as discoverable device
func (m *HomieRunner) Register(rootTopic string, meters map[uint8]*Meter, qe *ModbusEngine) {
	// mqttOpts.SetWill(m.homieTopic("$state"), "lost", byte(m.mqttQos), true)
	m.rootTopic = stripSlash(rootTopic)

	// devices
	for _, meter := range meters {
		m.publishMeter(meter, qe)
	}
}

// stripSlash removes trailing slash
func stripSlash(s string) string {
	if s[len(s)-1:] == "/" {
		s = s[:len(s)-1]
	}
	return s
}

func (m *HomieRunner) publishMeter(meter *Meter, qe *ModbusEngine) {
	descriptor := m.deviceDescriptor(meter, qe)

	// clear retained messages
	subTopic := m.DeviceTopic(meter.DeviceId)
	m.unpublish(subTopic)

	// device
	m.publish(subTopic+"/$homie", version)
	m.publish(subTopic+"/$name", "GoSDM")
	m.publish(subTopic+"/$state", "ready")
	// m.publish(subTopic+"/$implementation", "GoSDM")

	// node
	m.publish(subTopic+"/$nodes", nodeTopic)

	subTopic = fmt.Sprintf("%s/%s", subTopic, nodeTopic)
	m.publish(subTopic+"/$name", descriptor.Manufacturer)
	m.publish(subTopic+"/$type", descriptor.Model)

	// properties
	m.publishProperties(subTopic, meter, qe)
}

func (m *HomieRunner) deviceDescriptor(meter *Meter, qe *ModbusEngine) SunSpecDeviceDescriptor {
	descriptor := SunSpecDeviceDescriptor{
		Manufacturer: meter.Producer.GetMeterType(),
		Model:        nodeTopic,
	}

	if sunspec, ok := meter.Producer.(*SEProducer); ok {
		op := sunspec.GetSunSpecCommonBlock()
		snip := QuerySnip{
			DeviceId:  meter.DeviceId,
			Operation: op,
		}
		if b, err := qe.Query(snip); err == nil {
			if descriptor, err = sunspec.DecodeSunSpecCommonBlock(b); err != nil {
				log.Println(err)
			}
		} else {
			log.Println(err)
		}
	}

	return descriptor
}

func (m *HomieRunner) publishProperties(subtopic string, meter *Meter, qe *ModbusEngine) {
	meterOps := meter.Producer.Produce()

	// read from device to split block operations
	// TODO refactor transformation code into queryengine
	snips := make([]QuerySnip, 0)
	for _, op := range meterOps {
		snip := QuerySnip{
			DeviceId:  meter.DeviceId,
			Operation: op,
		}
		if b, err := qe.Query(snip); err == nil {
			for _, snip := range qe.Transform(snip, b) {
				snips = append(snips, snip)
			}
		}
	}

	// sort by measurement type
	sort.Slice(snips, func(a, b int) bool {
		return snips[a].IEC61850.String() < snips[b].IEC61850.String()
	})

	properties := make([]string, len(snips))
	re, _ := regexp.Compile(`^(.+) \((.+)\)$`)

	for i, operation := range snips {
		property := strings.ToLower(operation.IEC61850.String())
		properties[i] = property

		description := operation.IEC61850.Description()
		matches := re.FindStringSubmatch(description)
		if len(matches) == 3 {
			// strip unit from name
			description = matches[1]
		}

		propertySubtopic := fmt.Sprintf("%s/%s", subtopic, property)
		m.publish(propertySubtopic+"/$name", description)

		if len(matches) == 3 {
			unit := matches[2]
			m.publish(propertySubtopic+"/$unit", unit)
			m.publish(propertySubtopic+"/$datatype", "float")
		}
	}
	m.publish(subtopic+"/$properties", strings.Join(properties[:], ","))
}

func (m *HomieRunner) publish(subtopic string, message string) {
	topic := m.rootTopic + "/" + subtopic
	m.Publish(topic, true, message)
}

// unpublish retained message hierarchy
func (m *HomieRunner) unpublish(subtopic string) {
	topic := fmt.Sprintf("%s/%s/#", m.rootTopic, subtopic)
	if m.verbose {
		log.Printf("MQTT: cleaning %s", topic)
	}

	tokens := make([]MQTT.Token, 0)
	tokens = append(tokens, m.client.Subscribe(topic, byte(m.mqttQos), func(c MQTT.Client, msg MQTT.Message) {
		topic := msg.Topic()
		token := m.client.Publish(topic, byte(m.mqttQos), true, []byte{})
		if m.verbose {
			log.Printf("MQTT: cleaned %s", topic)
		}
		tokens = append(tokens, token)
	}))

	// wait for tokens
	for _, token := range tokens {
		m.WaitForToken(token)
	}

	// stop listening
	token := m.client.Unsubscribe(topic)
	m.WaitForToken(token)
}
<commit_msg>Fix publishing unit and datatype (#99)<commit_after>package sdm630

import (
	"fmt"
	"log"
	"regexp"
	"sort"
	"strings"

	MQTT "github.com/eclipse/paho.mqtt.golang"

	. "github.com/gonium/gosdm630/internal/meters"
)

const (
	version   = "3.0.1"
	nodeTopic = "meter"
)

type HomieRunner struct {
	*MqttClient
	rootTopic string
}

// Run MQTT client publisher
func (m *HomieRunner) Run(in QuerySnipChannel, rate int) {
	rateMap := make(RateMap)

	for {
		snip := <-in
		topic := fmt.Sprintf("%s/%s/%s/%s",
			m.rootTopic,
			m.DeviceTopic(snip.DeviceId),
			nodeTopic,
			strings.ToLower(snip.IEC61850.String()))

		if rateMap.Allowed(rate, topic) {
			message := fmt.Sprintf("%.3f", snip.Value)
			go m.Publish(topic, false, message)
		} else {
			if m.verbose {
				log.Printf("MQTT: skipped %s, rate to high", topic)
			}
		}
	}
}

// Register subcribes GoSDM as discoverable device
func (m *HomieRunner) Register(rootTopic string, meters map[uint8]*Meter, qe *ModbusEngine) {
	// mqttOpts.SetWill(m.homieTopic("$state"), "lost", byte(m.mqttQos), true)
	m.rootTopic = stripSlash(rootTopic)

	// devices
	for _, meter := range meters {
		m.publishMeter(meter, qe)
	}
}

// stripSlash removes trailing slash
func stripSlash(s string) string {
	if s[len(s)-1:] == "/" {
		s = s[:len(s)-1]
	}
	return s
}

func (m *HomieRunner) publishMeter(meter *Meter, qe *ModbusEngine) {
	descriptor := m.deviceDescriptor(meter, qe)

	// clear retained messages
	subTopic := m.DeviceTopic(meter.DeviceId)
	m.unpublish(subTopic)

	// device
	m.publish(subTopic+"/$homie", version)
	m.publish(subTopic+"/$name", "GoSDM")
	m.publish(subTopic+"/$state", "ready")
	// m.publish(subTopic+"/$implementation", "GoSDM")

	// node
	m.publish(subTopic+"/$nodes", nodeTopic)

	subTopic = fmt.Sprintf("%s/%s", subTopic, nodeTopic)
	m.publish(subTopic+"/$name", descriptor.Manufacturer)
	m.publish(subTopic+"/$type", descriptor.Model)

	// properties
	m.publishProperties(subTopic, meter, qe)
}

func (m *HomieRunner) deviceDescriptor(meter *Meter, qe *ModbusEngine) SunSpecDeviceDescriptor {
	descriptor := SunSpecDeviceDescriptor{
		Manufacturer: meter.Producer.GetMeterType(),
		Model:        nodeTopic,
	}

	if sunspec, ok := meter.Producer.(*SEProducer); ok {
		op := sunspec.GetSunSpecCommonBlock()
		snip := QuerySnip{
			DeviceId:  meter.DeviceId,
			Operation: op,
		}
		if b, err := qe.Query(snip); err == nil {
			if descriptor, err = sunspec.DecodeSunSpecCommonBlock(b); err != nil {
				log.Println(err)
			}
		} else {
			log.Println(err)
		}
	}

	return descriptor
}

func (m *HomieRunner) publishProperties(subtopic string, meter *Meter, qe *ModbusEngine) {
	meterOps := meter.Producer.Produce()

	// read from device to split block operations
	// TODO refactor transformation code into queryengine
	snips := make([]QuerySnip, 0)
	for _, op := range meterOps {
		snip := QuerySnip{
			DeviceId:  meter.DeviceId,
			Operation: op,
		}
		if b, err := qe.Query(snip); err == nil {
			for _, snip := range qe.Transform(snip, b) {
				snips = append(snips, snip)
			}
		}
	}

	// sort by measurement type
	sort.Slice(snips, func(a, b int) bool {
		return snips[a].IEC61850.String() < snips[b].IEC61850.String()
	})

	properties := make([]string, len(snips))
	re, _ := regexp.Compile(`^(.+) \((.+)\)$`)

	for i, operation := range snips {
		property := strings.ToLower(operation.IEC61850.String())
		properties[i] = property

		var unit string
		description := operation.IEC61850.Description()
		matches := re.FindStringSubmatch(description)
		if len(matches) == 3 {
			// strip unit from name
			description = matches[1]
			unit = matches[2]
		}

		propertySubtopic := fmt.Sprintf("%s/%s", subtopic, property)
		m.publish(propertySubtopic+"/$name", description)

		m.publish(propertySubtopic+"/$unit", unit)
		m.publish(propertySubtopic+"/$datatype", "float")
	}
	m.publish(subtopic+"/$properties", strings.Join(properties[:], ","))
}

func (m *HomieRunner) publish(subtopic string, message string) {
	topic := m.rootTopic + "/" + subtopic
	m.Publish(topic, true, message)
}

// unpublish retained message hierarchy
func (m *HomieRunner) unpublish(subtopic string) {
	topic := fmt.Sprintf("%s/%s/#", m.rootTopic, subtopic)
	if m.verbose {
		log.Printf("MQTT: cleaning %s", topic)
	}

	tokens := make([]MQTT.Token, 0)
	tokens = append(tokens, m.client.Subscribe(topic, byte(m.mqttQos), func(c MQTT.Client, msg MQTT.Message) {
		topic := msg.Topic()
		token := m.client.Publish(topic, byte(m.mqttQos), true, []byte{})
		if m.verbose {
			log.Printf("MQTT: cleaned %s", topic)
		}
		tokens = append(tokens, token)
	}))

	// wait for tokens
	for _, token := range tokens {
		m.WaitForToken(token)
	}

	// stop listening
	token := m.client.Unsubscribe(topic)
	m.WaitForToken(token)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"net"
	"net/http"
	"sync"
)

type ipMap struct {
	sync.RWMutex
	m map[string]bool
}

type hookService struct {
	client       http.Client
	AddIPsUri    string
	RemoveIPsUri string
	SyncIPsUri   string
	hookedIPs    ipMap
}

func (h *hookService) send(ips []net.IP, u string) error {
	buf := new(bytes.Buffer)
	err := json.NewEncoder(buf).Encode(ips)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", u, buf)
	if err != nil {
		return err
	}

	resp, err := h.client.Do(req)
	if err != nil {
		return err
	}

	resp.Body.Close()

	return nil
}

func (h *hookService) Add(ip net.IP) error {
	h.hookedIPs.Lock()
	defer h.hookedIPs.Unlock()
	// Short circuit already sent IPs
	if h.hookedIPs.m[ip.String()] == true {
		return nil
	}
	err := h.send([]net.IP{ip}, h.AddIPsUri)
	if err != nil {
		return err
	}

	h.hookedIPs.m[ip.String()] = true

	return nil
}

func (h *hookService) Remove(ip net.IP) error {
	err := h.send([]net.IP{ip}, h.RemoveIPsUri)
	if err != nil {
		return err
	}

	h.hookedIPs.Lock()
	defer h.hookedIPs.Unlock()
	delete(h.hookedIPs.m, ip.String())

	return nil
}

func (h *hookService) Sync(ips []net.IP) error {
	if h.SyncIPsUri != "" {
		err := h.send(ips, h.SyncIPsUri)
		if err != nil {
			return err
		}

		h.hookedIPs.Lock()
		defer h.hookedIPs.Unlock()
		h.hookedIPs.m = make(map[string]bool)
		for _, ip := range ips {
			h.hookedIPs.m[ip.String()] = true
		}
	}

	return nil
}
<commit_msg>Rename send to sendHTTPHook.<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"net"
	"net/http"
	"sync"
)

type ipMap struct {
	sync.RWMutex
	m map[string]bool
}

type hookService struct {
	client       http.Client
	AddIPsUri    string
	RemoveIPsUri string
	SyncIPsUri   string
	hookedIPs    ipMap
}

func (h *hookService) sendHTTPHook(ips []net.IP, u string) error {
	buf := new(bytes.Buffer)
	err := json.NewEncoder(buf).Encode(ips)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", u, buf)
	if err != nil {
		return err
	}

	resp, err := h.client.Do(req)
	if err != nil {
		return err
	}

	resp.Body.Close()

	return nil
}

func (h *hookService) Add(ip net.IP) error {
	h.hookedIPs.Lock()
	defer h.hookedIPs.Unlock()
	// Short circuit already sent IPs
	if h.hookedIPs.m[ip.String()] == true {
		return nil
	}
	err := h.sendHTTPHook([]net.IP{ip}, h.AddIPsUri)
	if err != nil {
		return err
	}

	h.hookedIPs.m[ip.String()] = true

	return nil
}

func (h *hookService) Remove(ip net.IP) error {
	err := h.sendHTTPHook([]net.IP{ip}, h.RemoveIPsUri)
	if err != nil {
		return err
	}

	h.hookedIPs.Lock()
	defer h.hookedIPs.Unlock()
	delete(h.hookedIPs.m, ip.String())

	return nil
}

func (h *hookService) Sync(ips []net.IP) error {
	if h.SyncIPsUri != "" {
		err := h.sendHTTPHook(ips, h.SyncIPsUri)
		if err != nil {
			return err
		}

		h.hookedIPs.Lock()
		defer h.hookedIPs.Unlock()
		h.hookedIPs.m = make(map[string]bool)
		for _, ip := range ips {
			h.hookedIPs.m[ip.String()] = true
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ezekg/git-hound/Godeps/_workspace/src/gopkg.in/yaml.v2"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"io/ioutil"
	"path/filepath"
	"regexp"
)

// A Hound contains the local configuration filename and all regexp patterns
// used for sniffing git-diffs.
type Hound struct {
	Fails  []string `yaml:"fail"`
	Warns  []string `yaml:"warn"`
	Skips  []string `yaml:"skip"`
	config string
}

// New initializes a new Hound instance by parsing regexp patterns from a
// local configuration file and returns a status bool.
func (h *Hound) New() bool {
	config, err := h.loadConfig()
	if err != nil {
		return false
	}

	err = h.parse(config)
	if err != nil {
		return false
	}

	return true
}

// Sniff matches the passed git-diff hunk against all regexp patterns that
// were parsed from the local configuration.
func (h *Hound) Sniff(fileName string, hunk *diff.Hunk, smells chan<- smell, done chan<- bool) {
	defer func() { done <- true }()

	rxFileName, _ := regexp.Compile(`^\w+\/`)
	fileName = rxFileName.ReplaceAllString(fileName, "")
	if _, ok := h.matchPatterns(h.Skips, []byte(fileName)); ok {
		return
	}

	rxModLines, _ := regexp.Compile(`(?m)^\+\s*(.+)$`)
	matches := rxModLines.FindAllSubmatch(hunk.Body, -1)

	for _, match := range matches {
		line := match[1]

		if pattern, warned := h.matchPatterns(h.Warns, line); warned {
			smells <- smell{
				pattern:  pattern,
				fileName: fileName,
				line:     line,
				lineNum:  hunk.NewStartLine,
				severity: 1,
			}
		}

		if pattern, failed := h.matchPatterns(h.Fails, line); failed {
			smells <- smell{
				pattern:  pattern,
				fileName: fileName,
				line:     line,
				lineNum:  hunk.NewStartLine,
				severity: 2,
			}
		}
	}
}

// loadConfig reads a local configuration file of regexp patterns and returns
// the contents of the file.
func (h *Hound) loadConfig() ([]byte, error) {
	filename, _ := filepath.Abs(h.config)
	return ioutil.ReadFile(filename)
}

// parse parses a configuration byte array and returns an error.
func (h *Hound) parse(config []byte) error {
	return yaml.Unmarshal(config, h)
}

// match matches a byte array against a regexp pattern and returns a bool.
func (h *Hound) match(pattern string, subject []byte) bool {
	r, err := regexp.Compile(pattern)
	if err != nil {
		panic(err)
	}

	return r.Match(subject)
}

// matchPatterns matches a byte array against an array of regexp patterns and
// returns the matched pattern and a bool.
func (h *Hound) matchPatterns(patterns []string, subject []byte) (string, bool) {
	for _, pattern := range patterns {
		if match := h.match(pattern, subject); match {
			return pattern, true
		}
	}

	return "", false
}
<commit_msg>add cache for regexp compilation<commit_after>package main

import (
	"github.com/ezekg/git-hound/Godeps/_workspace/src/gopkg.in/yaml.v2"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"io/ioutil"
	"path/filepath"
	"regexp"
)

var (
	regexes = make(map[string]*regexp.Regexp)
)

// A Hound contains the local configuration filename and all regexp patterns
// used for sniffing git-diffs.
type Hound struct {
	Fails  []string `yaml:"fail"`
	Warns  []string `yaml:"warn"`
	Skips  []string `yaml:"skip"`
	config string
}

// New initializes a new Hound instance by parsing regexp patterns from a
// local configuration file and returns a status bool.
func (h *Hound) New() bool {
	config, err := h.loadConfig()
	if err != nil {
		return false
	}

	err = h.parse(config)
	if err != nil {
		return false
	}

	return true
}

// Sniff matches the passed git-diff hunk against all regexp patterns that
// were parsed from the local configuration.
func (h *Hound) Sniff(fileName string, hunk *diff.Hunk, smells chan<- smell, done chan<- bool) {
	defer func() { done <- true }()

	rxFileName, _ := h.regexp(`^\w+\/`)
	fileName = rxFileName.ReplaceAllString(fileName, "")
	if _, ok := h.matchPatterns(h.Skips, []byte(fileName)); ok {
		return
	}

	rxModLines, _ := h.regexp(`(?m)^\+\s*(.+)$`)
	matches := rxModLines.FindAllSubmatch(hunk.Body, -1)

	for _, match := range matches {
		line := match[1]

		if pattern, warned := h.matchPatterns(h.Warns, line); warned {
			smells <- smell{
				pattern:  pattern,
				fileName: fileName,
				line:     line,
				lineNum:  hunk.NewStartLine,
				severity: 1,
			}
		}

		if pattern, failed := h.matchPatterns(h.Fails, line); failed {
			smells <- smell{
				pattern:  pattern,
				fileName: fileName,
				line:     line,
				lineNum:  hunk.NewStartLine,
				severity: 2,
			}
		}
	}
}

// loadConfig reads a local configuration file of regexp patterns and returns
// the contents of the file.
func (h *Hound) loadConfig() ([]byte, error) {
	filename, _ := filepath.Abs(h.config)
	return ioutil.ReadFile(filename)
}

// parse parses a configuration byte array and returns an error.
func (h *Hound) parse(config []byte) error {
	return yaml.Unmarshal(config, h)
}

// getRegexp looks for the specified pattern in Hound's regexes cache, and if
// it is available, it will fetch from it. If it is not available, it
// will compile the pattern and store it in the cache. Returns a Regexp
// and an error.
func (h *Hound) regexp(pattern string) (*regexp.Regexp, error) {
	if regexes[pattern] != nil {
		return regexes[pattern], nil
	}

	r, err := regexp.Compile(pattern)
	if err == nil {
		regexes[pattern] = r
	}

	return r, err
}

// match matches a byte array against a regexp pattern and returns a bool.
func (h *Hound) match(pattern string, subject []byte) bool {
	r, err := h.regexp(pattern)
	if err != nil {
		panic(err)
	}

	return r.Match(subject)
}

// matchPatterns matches a byte array against an array of regexp patterns and
// returns the matched pattern and a bool.
func (h *Hound) matchPatterns(patterns []string, subject []byte) (string, bool) {
	for _, pattern := range patterns {
		if match := h.match(pattern, subject); match {
			return pattern, true
		}
	}

	return "", false
}
<|endoftext|>


<commit_before>package husky

import (
	"strings"
)

type app struct {
	Router  *Router
	Config  *Config
	Server  *Server
	Command *Arguments
}

func NewApp() *app {
	return &app{
		Router:  NewRouter(),
		Config:  NewConfig(),
		Server:  NewServer(),
		Command: NewArguments(),
	}
}

type HuskyHandler func(dispatcher *Dispatcher)

func (app *app) joinPath(path string) string {
	p, _ := app.Config.Get("path")
	joined := p.(string) + path

	return "/" + strings.TrimLeft(joined, "/")
}

func (app *app) Post(route string, handler HuskyHandler) {
	app.Router.Bind("POST", app.joinPath(route), handler)
}

func (app *app) Get(route string, handler HuskyHandler) {
	app.Router.Bind("GET", app.joinPath(route), handler)
}

func (app *app) Put(route string, handler HuskyHandler) {
	app.Router.Bind("PUT", app.joinPath(route), handler)
}

func (app *app) Delete(route string, handler HuskyHandler) {
	app.Router.Bind("DELETE", app.joinPath(route), handler)
}

func (app *app) Notfound(route string, handler HuskyHandler) {
	app.Router.Bind("404", app.joinPath(route), handler)
}

func (app *app) AcceptCORS() {
	app.Router.Bind("OPTIONS", "/", func(d *Dispatcher) {
		d.Output.SetStatus(204)
		d.Output.SetHeader("Access-Control-Allow-Origin", "*")
		d.Output.SetHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
		d.Output.SetHeader("Access-Control-Allow-Headers", "X-Requested-With")
		d.Output.SendHeader()
	})
}

func (app *app) Serve() {
	app.Server.Listen(app.Config, app.Router)
}
<commit_msg>Allowed to custom CORS headers<commit_after>package husky

import (
	"strings"
)

type app struct {
	Router  *Router
	Config  *Config
	Server  *Server
	Command *Arguments
}

func NewApp() *app {
	return &app{
		Router:  NewRouter(),
		Config:  NewConfig(),
		Server:  NewServer(),
		Command: NewArguments(),
	}
}

type HuskyHandler func(dispatcher *Dispatcher)

func (app *app) joinPath(path string) string {
	p, _ := app.Config.Get("path")
	joined := p.(string) + path

	return "/" + strings.TrimLeft(joined, "/")
}

func (app *app) Post(route string, handler HuskyHandler) {
	app.Router.Bind("POST", app.joinPath(route), handler)
}

func (app *app) Get(route string, handler HuskyHandler) {
	app.Router.Bind("GET", app.joinPath(route), handler)
}

func (app *app) Put(route string, handler HuskyHandler) {
	app.Router.Bind("PUT", app.joinPath(route), handler)
}

func (app *app) Delete(route string, handler HuskyHandler) {
	app.Router.Bind("DELETE", app.joinPath(route), handler)
}

func (app *app) Notfound(route string, handler HuskyHandler) {
	app.Router.Bind("404", app.joinPath(route), handler)
}

func (app *app) AcceptCORS(extraHeaders []string) {
	app.Router.Bind("OPTIONS", "/", func(d *Dispatcher) {
		d.Output.SetStatus(204)
		d.Output.SetHeader("Access-Control-Allow-Origin", "*")
		d.Output.SetHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
		d.Output.SetHeader("Access-Control-Allow-Headers", strings.Join(extraHeaders, ","))
		d.Output.SendHeader()
	})
}

func (app *app) Serve() {
	app.Server.Listen(app.Config, app.Router)
}
<|endoftext|>


<commit_before>// Copyright © 2016 Mark Bates <mark@markbates.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package generate

import (
	"errors"
	"fmt"
	"path/filepath"

	"github.com/markbates/gentronics"
	"github.com/markbates/inflect"
	"github.com/spf13/cobra"
)

// ResourceCmd generates a new actions/resource file and a stub test.
var ResourceCmd = &cobra.Command{
	Use:     "resource [name]",
	Aliases: []string{"r"},
	Short:   "Generates a new actions/resource file",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) == 0 {
			return errors.New("you must specify a resource name")
		}
		name := args[0]
		data := gentronics.Data{
			"name":     name,
			"singular": inflect.Singularize(name),
			"plural":   inflect.Pluralize(name),
			"camel":    inflect.Camelize(name),
			"under":    inflect.Underscore(name),
			"actions":  []string{"List", "Show", "New", "Create", "Edit", "Update", "Destroy"},
		}
		return NewResourceGenerator(data).Run(".", data)
	},
}

// NewResourceGenerator generates a new actions/resource file and a stub test.
func NewResourceGenerator(data gentronics.Data) *gentronics.Generator {
	g := gentronics.New()
	g.Add(gentronics.NewFile(filepath.Join("actions", fmt.Sprintf("%s.go", data["under"])), rAction))
	g.Add(gentronics.NewFile(filepath.Join("actions", fmt.Sprintf("%s_test.go", data["under"])), rResourceTest))
	g.Add(&gentronics.Func{
		Should: func(data gentronics.Data) bool { return true },
		Runner: func(root string, data gentronics.Data) error {
			return addInsideAppBlock("var resource buffalo.Resource",
				fmt.Sprintf("resource = &%sResource{&buffalo.BaseResource{}}", data["camel"]),
				fmt.Sprintf("app.Resource(\"/%s\", resource)", data["under"]),
			)
		},
	})
	g.Add(Fmt)
	return g
}

var rAction = `package actions

import "github.com/gobuffalo/buffalo"

type {{camel}}Resource struct{
	buffalo.Resource
}

{{#each actions}}
// {{.}} default implementation.
func (v *{{camel}}Resource) {{.}}(c buffalo.Context) error {
	return c.Render(200, r.String("{{camel}}#{{.}}"))
}

{{/each}}
`

var rResourceTest = `package actions_test

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_{{camel}}Resource_List(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Show(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_New(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Create(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Edit(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Update(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Destroy(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}
`
<commit_msg>[#198] moving resource generator to avoid pointers<commit_after>// Copyright © 2016 Mark Bates <mark@markbates.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package generate

import (
	"errors"
	"fmt"
	"path/filepath"

	"github.com/markbates/gentronics"
	"github.com/markbates/inflect"
	"github.com/spf13/cobra"
)

// ResourceCmd generates a new actions/resource file and a stub test.
var ResourceCmd = &cobra.Command{
	Use:     "resource [name]",
	Aliases: []string{"r"},
	Short:   "Generates a new actions/resource file",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) == 0 {
			return errors.New("you must specify a resource name")
		}
		name := args[0]
		data := gentronics.Data{
			"name":     name,
			"singular": inflect.Singularize(name),
			"plural":   inflect.Pluralize(name),
			"camel":    inflect.Camelize(name),
			"under":    inflect.Underscore(name),
			"actions":  []string{"List", "Show", "New", "Create", "Edit", "Update", "Destroy"},
		}
		return NewResourceGenerator(data).Run(".", data)
	},
}

// NewResourceGenerator generates a new actions/resource file and a stub test.
func NewResourceGenerator(data gentronics.Data) *gentronics.Generator {
	g := gentronics.New()
	g.Add(gentronics.NewFile(filepath.Join("actions", fmt.Sprintf("%s.go", data["under"])), rAction))
	g.Add(gentronics.NewFile(filepath.Join("actions", fmt.Sprintf("%s_test.go", data["under"])), rResourceTest))
	g.Add(&gentronics.Func{
		Should: func(data gentronics.Data) bool { return true },
		Runner: func(root string, data gentronics.Data) error {
			return addInsideAppBlock("var resource buffalo.Resource",
				fmt.Sprintf("resource = &%sResource{&buffalo.BaseResource{}}", data["camel"]),
				fmt.Sprintf("app.Resource(\"/%s\", resource)", data["under"]),
			)
		},
	})
	g.Add(Fmt)
	return g
}

var rAction = `package actions

import "github.com/gobuffalo/buffalo"

type {{camel}}Resource struct{
	buffalo.Resource
}

{{#each actions}}
// {{.}} default implementation.
func (v {{camel}}Resource) {{.}}(c buffalo.Context) error {
	return c.Render(200, r.String("{{camel}}#{{.}}"))
}

{{/each}}
`

var rResourceTest = `package actions_test

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func Test_{{camel}}Resource_List(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Show(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_New(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Create(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Edit(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Update(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}

func Test_{{camel}}Resource_Destroy(t *testing.T) {
	r := require.New(t)
	r.Fail("Not Implemented!")
}
`
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/animenotifier/arn"
	"github.com/bwmarrin/discordgo"
)

// Session provides access to the Discord session.
var discord *discordgo.Session

func main() {
	var err error

	discord, _ = discordgo.New()
	discord.Token = "Bot " + arn.APIKeys.Discord.Token

	// Verify a Token was provided
	if discord.Token == "" {
		log.Println("You must provide a Discord authentication token.")
		return
	}

	// Verify the Token is valid and grab user information
	discord.State.User, err = discord.User("@me")

	if err != nil {
		log.Printf("Error fetching user information: %s\n", err)
	}

	// Open a websocket connection to Discord
	err = discord.Open()

	if err != nil {
		log.Printf("Error opening connection to Discord, %s\n", err)
	}

	defer discord.Close()

	// Receive messages
	discord.AddHandler(onMessage)

	// Wait for a CTRL-C
	log.Printf("Tsundere is ready. Press CTRL-C to exit.")
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
	<-sc
}

// This function will be called every time a new message is created on any channel.
func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
	// Ignore all messages created by the bot itself
	if m.Author.ID == s.State.User.ID {
		return
	}

	if m.Content == "!commands" {
		s.ChannelMessageSend(m.ChannelID, `
**!user** [username]
**!anime** [id]
**!animelist** [username]
**!tag** [forum tag]`)
	}

	// Has the bot been mentioned?
	for _, user := range m.Mentions {
		if user.ID == discord.State.User.ID {
			s.ChannelMessageSend(m.ChannelID, m.Author.Mention()+" :heart:")
			return
		}
	}

	if strings.HasPrefix(m.Content, "!user ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/+"+strings.Split(m.Content, " ")[1])
		return
	}

	if strings.HasPrefix(m.Content, "!anime ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/anime/"+strings.Split(m.Content, " ")[1])
		return
	}

	if strings.HasPrefix(m.Content, "!animelist ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/+"+strings.Split(m.Content, " ")[1]+"/animelist")
		return
	}

	if strings.HasPrefix(m.Content, "!tag ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/forum/"+strings.ToLower(strings.Split(m.Content, " ")[1]))
		return
	}

	if strings.HasPrefix(m.Content, "!s ") {
		term := m.Content[len("!s "):]
		userResults, animeResults := arn.Search(term, 3, 3)
		message := ""

		for _, user := range userResults {
			message += "https://notify.moe" + user.Link() + "\n"
		}

		for _, anime := range animeResults {
			message += "https://notify.moe" + anime.Link() + "\n"
		}

		if len(userResults) == 0 && len(animeResults) == 0 {
			message = "Sorry, I couldn't find any anime or users with that term."
		}

		s.ChannelMessageSend(m.ChannelID, message)
		return
	}
}
<commit_msg>Fixed discord bot<commit_after>package main

import (
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/animenotifier/arn"
	"github.com/bwmarrin/discordgo"
)

// Session provides access to the Discord session.
var discord *discordgo.Session

func main() {
	var err error

	discord, _ = discordgo.New()
	discord.Token = "Bot " + arn.APIKeys.Discord.Token

	// Verify a Token was provided
	if discord.Token == "" {
		log.Println("You must provide a Discord authentication token.")
		return
	}

	// Verify the Token is valid and grab user information
	discord.State.User, err = discord.User("@me")

	if err != nil {
		log.Printf("Error fetching user information: %s\n", err)
	}

	// Open a websocket connection to Discord
	err = discord.Open()

	if err != nil {
		log.Printf("Error opening connection to Discord, %s\n", err)
	}

	defer discord.Close()

	// Receive messages
	discord.AddHandler(onMessage)

	// Wait for a CTRL-C
	log.Printf("Tsundere is ready. Press CTRL-C to exit.")
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
	<-sc
}

// This function will be called every time a new message is created on any channel.
func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
	// Ignore all messages created by the bot itself
	if m.Author.ID == s.State.User.ID {
		return
	}

	if m.Content == "!commands" {
		s.ChannelMessageSend(m.ChannelID, `
**!user** [username]
**!anime** [id]
**!animelist** [username]
**!tag** [forum tag]`)
	}

	// Has the bot been mentioned?
	for _, user := range m.Mentions {
		if user.ID == discord.State.User.ID {
			s.ChannelMessageSend(m.ChannelID, m.Author.Mention()+" :heart:")
			return
		}
	}

	if strings.HasPrefix(m.Content, "!user ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/+"+strings.Split(m.Content, " ")[1])
		return
	}

	if strings.HasPrefix(m.Content, "!anime ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/anime/"+strings.Split(m.Content, " ")[1])
		return
	}

	if strings.HasPrefix(m.Content, "!animelist ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/+"+strings.Split(m.Content, " ")[1]+"/animelist")
		return
	}

	if strings.HasPrefix(m.Content, "!tag ") {
		s.ChannelMessageSend(m.ChannelID, "https://notify.moe/forum/"+strings.ToLower(strings.Split(m.Content, " ")[1]))
		return
	}

	if strings.HasPrefix(m.Content, "!s ") {
		term := m.Content[len("!s "):]
		users, animes, posts, threads := arn.Search(term, 3, 3, 3, 3)
		message := ""

		for _, user := range users {
			message += "https://notify.moe" + user.Link() + "\n"
		}

		for _, anime := range animes {
			message += "https://notify.moe" + anime.Link() + "\n"
		}

		for _, post := range posts {
			message += "https://notify.moe" + post.Link() + "\n"
		}

		for _, thread := range threads {
			message += "https://notify.moe" + thread.Link() + "\n"
		}

		if len(users) == 0 && len(animes) == 0 && len(posts) == 0 && len(threads) == 0 {
			message = "Sorry, I couldn't find anything using that term."
		}

		s.ChannelMessageSend(m.ChannelID, message)
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("failed in function main()")
	}
}

var projectName string
var projectRate int
var projectPeriod int
var projectGoal int
var projectTimes int
var projectBenifary string
var projectState string
var currentPrice float64
var projectSummary int
var userList []string
var shareList map[string]int
var availableList map[string]int

//Init comment
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//started to initialize the projectState
	//step1: check whether args == 5
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}

	//step 2, intialize the project properties
	projectName = args[0]
	stub.PutState("projectName", projectName)

	projectRate, _ = strconv.Atoi(args[1])
	if projectRate <= 0 {
		return nil, errors.New("errors in args[1], it cannot be negative")
	}
	stub.PutState("projectRate", projectRate)

	projectPeriod, _ = strconv.Atoi(args[2])
	if projectPeriod <= 0 {
		return nil, errors.New("errors in args[2], it cannot be negative")
	}
	stub.PutState("projectPeriod", projectPeriod)

	projectGoal, _ = strconv.Atoi(args[3])
	if projectGoal <= 0 {
		return nil, errors.New("errors in args[3], it cannot be negative")
	}
	stub.PutState("projectGoal", projectGoal)

	projectTimes = 1
	stub.PutState("projectTimes", projectTimes)

	projectBenifary = args[4]
	stub.PutState("projectBenifary", projectBenifary)

	projectState = "draft"
	stub.PutState("projectState", projectState)

	currentPrice = 1.0
	stub.PutState("currentPrice", currentPrice)

	projectSummary = 0
	stub.PutState("projectSummary", projectSummary)

	return nil, nil
} //end of Init()

// Invoke comment
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")
	switch function {
	case "goPublic":
		fmt.Println("started logging in goPublic")
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		fmt.Println("started logging in pay()")

		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}

		//step1 : get args
		user := args[0]
		amount, _ := strconv.Atoi(args[1])
		if amount <= 0 {
			return nil, errors.New("errors in args[1],it is negative")
		}

		//step2 : check if the userList[user] exist
		//if exist, then userList[user] += amount
		//if not exists, then userList[user] = amount
		if shareList[user] == 0 {
			fmt.Printf("the user [%v] does not exit \n", user)
			userList = append(userList, user)
			shareList[user] = amount

		} else {
			fmt.Printf("the user [%v] exist", user)
			if !GoalReached() {
				shareList[user] += amount
			}
		}

		// step3: raise amount

		//// TODO: write code for pay
		return nil, nil
	case "checkGoalReached":
		fmt.Println("started logging in checkGoalReached()")
		// TODO: write code for checkGoalReached
		return nil, nil
	case "checkDaoqi":
		fmt.Println("started logging in checkDaoqi()")
		// TODO: write code for checkDaoqi
		return nil, nil
	case "calculatePrice":
		fmt.Println("started logging in calculatePrice")
		return nil, nil
	case "calculateResult":
		fmt.Println("started logging in calculateResult")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

// Query comment
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")
	switch function {
	case "getProjectName":
		result, err := stub.GetState("projectName")
		if err != nil {
			return nil, errors.New("error in getProjectName")
		}
		return result, nil
	// case "getProjectState":
	// 	fmt.Println("started logging in getProjectState()")
	// 	if len(args) != 0 {
	// 		return nil, errors.New("incorrect args")
	// 	}
	// 	result := projectName + "/"
	// 	result += strconv.Itoa(projectRate) + "/"
	// 	result += strconv.Itoa(projectPeriod) + "/"
	// 	result += strconv.Itoa(projectGoal) + "/"
	// 	result += strconv.Itoa(projectTimes) + "/"
	// 	result += projectBenifary + "/"
	// 	result += projectState + "/"
	// 	result += strconv.FormatFloat(currentPrice, 'E', -1, 64) + "/"
	// 	result += strconv.Itoa(projectSummary) + "/"
	//
	// 	return []byte(result), nil //end of getProjectState
	case "getUserList":
		fmt.Println("started logging in getUserList")
		var result string
		for i, value := range userList {
			result += fmt.Sprintf("userList[%v] is %v ****", strconv.Itoa(i), value)
		}
		return []byte(result), nil
	case "getShareList":
		fmt.Println("started logging in getShareList")
		return nil, nil
	case "getAvailableList":
		fmt.Println("started logging in getAvailableList")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

func GoalReached() bool {
	return false
}
<commit_msg>demo7.go<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("failed in function main()")
	}
}

var projectName string
var projectRate int
var projectPeriod int
var projectGoal int
var projectTimes int
var projectBenifary string
var projectState string
var currentPrice float64
var projectSummary int
var userList []string
var shareList map[string]int
var availableList map[string]int

//Init comment
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//started to initialize the projectState
	//step1: check whether args == 5
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}

	//step 2, intialize the project properties
	projectName = args[0]
	stub.PutState("projectName", []byte(projectName))

	projectRate, _ = strconv.Atoi(args[1])
	if projectRate <= 0 {
		return nil, errors.New("errors in args[1], it cannot be negative")
	}
	stub.PutState("projectRate", []byte(args[1]))

	projectPeriod, _ = strconv.Atoi(args[2])
	if projectPeriod <= 0 {
		return nil, errors.New("errors in args[2], it cannot be negative")
	}
	stub.PutState("projectPeriod", []byte(args[2]))

	projectGoal, _ = strconv.Atoi(args[3])
	if projectGoal <= 0 {
		return nil, errors.New("errors in args[3], it cannot be negative")
	}
	stub.PutState("projectGoal", []byte(args[3]))

	projectTimes = 1
	stub.PutState("projectTimes", []byte(strconv.Itoa(projectTimes)))

	projectBenifary = args[4]
	stub.PutState("projectBenifary", []byte(args[4]))

	projectState = "draft"
	stub.PutState("projectState", []byte(projectState))

	currentPrice = 1.0
	projectSummary = 0

	return nil, nil
} //end of Init()

// Invoke comment
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")
	switch function {
	case "goPublic":
		fmt.Println("started logging in goPublic")
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		fmt.Println("started logging in pay()")

		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}

		//step1 : get args
		user := args[0]
		amount, _ := strconv.Atoi(args[1])
		if amount <= 0 {
			return nil, errors.New("errors in args[1],it is negative")
		}

		//step2 : check if the userList[user] exist
		//if exist, then userList[user] += amount
		//if not exists, then userList[user] = amount
		if shareList[user] == 0 {
			fmt.Printf("the user [%v] does not exit \n", user)
			userList = append(userList, user)
			shareList[user] = amount

		} else {
			fmt.Printf("the user [%v] exist", user)
			if !GoalReached() {
				shareList[user] += amount
			}
		}

		// step3: raise amount

		//// TODO: write code for pay
		return nil, nil
	case "checkGoalReached":
		fmt.Println("started logging in checkGoalReached()")
		// TODO: write code for checkGoalReached
		return nil, nil
	case "checkDaoqi":
		fmt.Println("started logging in checkDaoqi()")
		// TODO: write code for checkDaoqi
		return nil, nil
	case "calculatePrice":
		fmt.Println("started logging in calculatePrice")
		return nil, nil
	case "calculateResult":
		fmt.Println("started logging in calculateResult")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

// Query comment
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")
	switch function {
	case "getProjectName":
		result, err := stub.GetState("projectName")
		if err != nil {
			return nil, errors.New("error in getProjectName")
		}
		return result, nil
	// case "getProjectState":
	// 	fmt.Println("started logging in getProjectState()")
	// 	if len(args) != 0 {
	// 		return nil, errors.New("incorrect args")
	// 	}
	// 	result := projectName + "/"
	// 	result += strconv.Itoa(projectRate) + "/"
	// 	result += strconv.Itoa(projectPeriod) + "/"
	// 	result += strconv.Itoa(projectGoal) + "/"
	// 	result += strconv.Itoa(projectTimes) + "/"
	// 	result += projectBenifary + "/"
	// 	result += projectState + "/"
	// 	result += strconv.FormatFloat(currentPrice, 'E', -1, 64) + "/"
	// 	result += strconv.Itoa(projectSummary) + "/"
	//
	// 	return []byte(result), nil //end of getProjectState
	case "getUserList":
		fmt.Println("started logging in getUserList")
		var result string
		for i, value := range userList {
			result += fmt.Sprintf("userList[%v] is %v ****", strconv.Itoa(i), value)
		}
		return []byte(result), nil
	case "getShareList":
		fmt.Println("started logging in getShareList")
		return nil, nil
	case "getAvailableList":
		fmt.Println("started logging in getAvailableList")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

func GoalReached() bool {
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("failed in function main()")
	}
}

var projectName string
var projectRate int
var projectPeriod int
var projectGoal int
var projectTimes int
var projectBenifary string
var projectState string
var currentPrice float64
var projectSummary int
var userList []string
var shareList map[string]int
var availableList map[string]int

//Init comment
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//started to initialize the projectState
	//step1: check whether args == 5
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}

	//step 2, intialize the project properties
	projectName = args[0]
	stub.PutState("projectName", []byte(projectName))

	projectRate, _ = strconv.Atoi(args[1])
	if projectRate <= 0 {
		return nil, errors.New("errors in args[1], it cannot be negative")
	}
	stub.PutState("projectRate", []byte(args[1]))

	projectPeriod, _ = strconv.Atoi(args[2])
	if projectPeriod <= 0 {
		return nil, errors.New("errors in args[2], it cannot be negative")
	}
	stub.PutState("projectPeriod", []byte(args[2]))

	projectGoal, _ = strconv.Atoi(args[3])
	if projectGoal <= 0 {
		return nil, errors.New("errors in args[3], it cannot be negative")
	}
	stub.PutState("projectGoal", []byte(args[3]))

	projectTimes = 1
	stub.PutState("projectTimes", []byte(strconv.Itoa(projectTimes)))

	projectBenifary = args[4]
	stub.PutState("projectBenifary", []byte(args[4]))

	projectState = "draft"
	stub.PutState("projectState", []byte(projectState))

	currentPrice = 1.0
	projectSummary = 0

	return nil, nil
} //end of Init()

// Invoke comment
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")
	switch function {
	case "goPublic":
		fmt.Println("started logging in goPublic")
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		fmt.Println("started logging in pay()")

		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}

		//step1 : get args
		user := args[0]
		amount, _ := strconv.Atoi(args[1])
		if amount <= 0 {
			return nil, errors.New("errors in args[1],it is negative")
		}

		//step2 : check if the userList[user] exist
		//if exist, then userList[user] += amount
		//if not exists, then userList[user] = amount
		if shareList[user] == 0 {
			fmt.Printf("the user [%v] does not exit \n", user)
			userList = append(userList, user)
			shareList[user] = amount

		} else {
			fmt.Printf("the user [%v] exist", user)
			if !GoalReached() {
				shareList[user] += amount
			}
		}

		// step3: raise amount

		//// TODO: write code for pay
		return nil, nil
	case "checkGoalReached":
		fmt.Println("started logging in checkGoalReached()")
		// TODO: write code for checkGoalReached
		return nil, nil
	case "checkDaoqi":
		fmt.Println("started logging in checkDaoqi()")
		// TODO: write code for checkDaoqi
		return nil, nil
	case "calculatePrice":
		fmt.Println("started logging in calculatePrice")
		return nil, nil
	case "calculateResult":
		fmt.Println("started logging in calculateResult")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

// Query comment
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")
	switch function {
	case "getProjectName":
		result, err := stub.GetState("projectName")
		if err != nil {
			return nil, errors.New("error in getProjectName")
		}
		return result, nil
	// case "getProjectState":
	// 	fmt.Println("started logging in getProjectState()")
	// 	if len(args) != 0 {
	// 		return nil, errors.New("incorrect args")
	// 	}
	// 	result := projectName + "/"
	// 	result += strconv.Itoa(projectRate) + "/"
	// 	result += strconv.Itoa(projectPeriod) + "/"
	// 	result += strconv.Itoa(projectGoal) + "/"
	// 	result += strconv.Itoa(projectTimes) + "/"
	// 	result += projectBenifary + "/"
	// 	result += projectState + "/"
	// 	result += strconv.FormatFloat(currentPrice, 'E', -1, 64) + "/"
	// 	result += strconv.Itoa(projectSummary) + "/"
	//
	// 	return []byte(result), nil //end of getProjectState
	case "getUserList":
		fmt.Println("started logging in getUserList")
		var result string
		for i, value := range userList {
			result += fmt.Sprintf("userList[%v] is %v ****", strconv.Itoa(i), value)
		}
		return []byte(result), nil
	case "getShareList":
		fmt.Println("started logging in getShareList")
		return nil, nil
	case "getAvailableList":
		fmt.Println("started logging in getAvailableList")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

func GoalReached() bool {
	return false
}
<commit_msg>demo7.go<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("failed in function main()")
	}
}

var projectName string
var projectRate int
var projectPeriod int
var projectGoal int
var projectTimes int
var projectBenifary string
var projectState string
var currentPrice float64
var projectSummary int
var userList []string
var shareList map[string]int
var availableList map[string]int

//Init comment
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//started to initialize the projectState
	//step1: check whether args == 5
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}

	//step 2, intialize the project properties
	projectName = args[0]
	stub.PutState("projectName", []byte(projectName))

	projectRate, _ = strconv.Atoi(args[1])
	if projectRate <= 0 {
		return nil, errors.New("errors in args[1], it cannot be negative")
	}
	stub.PutState("projectRate", []byte(args[1]))

	projectPeriod, _ = strconv.Atoi(args[2])
	if projectPeriod <= 0 {
		return nil, errors.New("errors in args[2], it cannot be negative")
	}
	stub.PutState("projectPeriod", []byte(args[2]))

	projectGoal, _ = strconv.Atoi(args[3])
	if projectGoal <= 0 {
		return nil, errors.New("errors in args[3], it cannot be negative")
	}
	stub.PutState("projectGoal", []byte(args[3]))

	projectTimes = 1
	stub.PutState("projectTimes", []byte(strconv.Itoa(projectTimes)))

	projectBenifary = args[4]
	stub.PutState("projectBenifary", []byte(args[4]))

	projectState = "draft"
	stub.PutState("projectState", []byte(projectState))

	currentPrice = 1.0
	projectSummary = 0

	return nil, nil
} //end of Init()

// Invoke comment
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")
	switch function {
	case "goPublic":
		fmt.Println("started logging in goPublic")
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		fmt.Println("started logging in pay()")

		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}

		//step1 : get args
		user := args[0]
		amount, _ := strconv.Atoi(args[1])
		if amount <= 0 {
			return nil, errors.New("errors in args[1],it is negative")
		}
		fmt.Printf("user is %v and amount is %v", user, amount)

		//step2 : check if the userList[user] exist
		//if exist, then userList[user] += amount
		//if not exists, then userList[user] = amount
		// if shareList[user] == 0 {
		// 	fmt.Printf("the user [%v] does not exit \n", user)
		// 	userList = append(userList, user)
		// 	shareList[user] = amount
		//
		// } else {
		// 	fmt.Printf("the user [%v] exist", user)
		// 	if !GoalReached() {
		// 		shareList[user] += amount
		// 	}
		// }

		// step3: raise amount

		//// TODO: write code for pay
		return nil, nil
	case "checkGoalReached":
		fmt.Println("started logging in checkGoalReached()")
		// TODO: write code for checkGoalReached
		return nil, nil
	case "checkDaoqi":
		fmt.Println("started logging in checkDaoqi()")
		// TODO: write code for checkDaoqi
		return nil, nil
	case "calculatePrice":
		fmt.Println("started logging in calculatePrice")
		return nil, nil
	case "calculateResult":
		fmt.Println("started logging in calculateResult")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

// Query comment
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")
	switch function {
	case "getProjectName":
		result, err := stub.GetState("projectName")
		if err != nil {
			return nil, errors.New("error in getProjectName")
		}
		return result, nil
	// case "getProjectState":
	// 	fmt.Println("started logging in getProjectState()")
	// 	if len(args) != 0 {
	// 		return nil, errors.New("incorrect args")
	// 	}
	// 	result := projectName + "/"
	// 	result += strconv.Itoa(projectRate) + "/"
	// 	result += strconv.Itoa(projectPeriod) + "/"
	// 	result += strconv.Itoa(projectGoal) + "/"
	// 	result += strconv.Itoa(projectTimes) + "/"
	// 	result += projectBenifary + "/"
	// 	result += projectState + "/"
	// 	result += strconv.FormatFloat(currentPrice, 'E', -1, 64) + "/"
	// 	result += strconv.Itoa(projectSummary) + "/"
	//
	// 	return []byte(result), nil //end of getProjectState
	case "getUserList":
		fmt.Println("started logging in getUserList")
		var result string
		for i, value := range userList {
			result += fmt.Sprintf("userList[%v] is %v ****", strconv.Itoa(i), value)
		}
		return []byte(result), nil
	case "getShareList":
		fmt.Println("started logging in getShareList")
		return nil, nil
	case "getAvailableList":
		fmt.Println("started logging in getAvailableList")
		return nil, nil
	default:
		fmt.Println("no function found")
		return nil, errors.New("no function found, recheck your function name")
	}
}

func GoalReached() bool {
	return false
}
<|endoftext|>


<commit_before>// Copyright 2013 Fredrik Ehnbom
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package text

import (
	"fmt"
)

type (
	// Defines a Region from point A to B.
	// A can be less than B, in which case
	// the selection is inverted.
	Region struct {
		A, B int
	}
)

func (r Region) String() string {
	return fmt.Sprintf("(%d, %d)", r.A, r.B)
}

// Returns the starting point of the region,
// that would be whichever of A and B
// is the minimal value.
func (r Region) Begin() int {
	return Min(r.A, r.B)
}

// Returns the ending point of the region,
// that would be whichever of A and B
// is the maximum value.
func (r Region) End() int {
	return Max(r.A, r.B)
}

// Returns whether the region contains the given
// point or not.
func (r Region) Contains(point int) bool {
	return point >= r.Begin() && point <= r.End()
}

// Returns whether the region fully covers the argument region
func (r Region) Covers(r2 Region) bool {
	return r.Contains(r2.Begin()) && r2.End() <= r.End()
}

// Returns whether the region is empty or not
func (r Region) Empty() bool {
	return r.A == r.B
}

// Returns the size of the region
func (r Region) Size() int {
	return r.End() - r.Begin()
}

// Returns a region covering both regions
func (r Region) Cover(other Region) Region {
	return Region{Min(r.Begin(), other.Begin()), Max(r.End(), other.End())}
}

// Clips this Region against the Region provided in the argument.
// That would be if any part of this region is inside of the
// region specified by the argument, that part of the region
// is removed from this region.
func (r Region) Clip(other Region) (ret Region) {
	if other.Covers(r) {
		// this region is a subregion within the other region
		return r
	}
	ret.A, ret.B = r.Begin(), r.End()
	other.A, other.B = other.Begin(), other.End()

	if ret.A >= other.A && ret.A < other.B {
		ret.A = other.B
	}
	if ret.B >= other.A && ret.B <= other.B {
		ret.B = other.A
	}
	if ret.B < ret.A {
		ret.B = ret.A
	}
	return
}

// Cuts away the parts of the region that is in the argument region.
// This is similar to Clip, except that the result can be multiple
// regions.
func (r Region) Cut(other Region) (ret []Region) {
	if r.Contains(other.A) {
		ret = append(ret, Region{r.A, other.A})
	}
	if r.Contains(other.B) {
		ret = append(ret, Region{other.B, r.B})
	}
	if len(ret) == 0 && !other.Covers(r) {
		ret = append(ret, r)
	}
	return
}

// Returns whether the two regions intersects or not
func (r Region) Intersects(other Region) bool {
	return r == other || r.Intersection(other).Size() > 0
}

// Returns the Region that is the intersection of the two
// regions given
func (r Region) Intersection(other Region) (ret Region) {
	if !r.Contains(other.Begin()) && !other.Contains(r.Begin()) {
		return
	}
	r2 := Region{Max(r.Begin(), other.Begin()), Min(r.End(), other.End())}
	if r2.Size() != 0 {
		ret = r2
	}
	return
}

// Adjusts the region in place for the given position and delta
func (r *Region) Adjust(position, delta int) {
	if r.A >= position {
		r.A += delta
	} else if diff := position + delta - r.A; diff < 0 {
		r.A += diff
	}
	if r.B >= position {
		r.B += delta
	} else if diff := position + delta - r.B; diff < 0 {
		r.B += diff
	}
}
<commit_msg>Preverse the direction of the original region when calling Cover.<commit_after>// Copyright 2013 Fredrik Ehnbom
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package text

import (
	"fmt"
)

type (
	// Defines a Region from point A to B.
	// A can be less than B, in which case
	// the selection is inverted.
	Region struct {
		A, B int
	}
)

func (r Region) String() string {
	return fmt.Sprintf("(%d, %d)", r.A, r.B)
}

// Returns the starting point of the region,
// that would be whichever of A and B
// is the minimal value.
func (r Region) Begin() int {
	return Min(r.A, r.B)
}

// Returns the ending point of the region,
// that would be whichever of A and B
// is the maximum value.
func (r Region) End() int {
	return Max(r.A, r.B)
}

// Returns whether the region contains the given
// point or not.
func (r Region) Contains(point int) bool {
	return point >= r.Begin() && point <= r.End()
}

// Returns whether the region fully covers the argument region
func (r Region) Covers(r2 Region) bool {
	return r.Contains(r2.Begin()) && r2.End() <= r.End()
}

// Returns whether the region is empty or not
func (r Region) Empty() bool {
	return r.A == r.B
}

// Returns the size of the region
func (r Region) Size() int {
	return r.End() - r.Begin()
}

// Returns a region covering both regions
func (r Region) Cover(other Region) Region {
	if r.A <= r.B {
		return Region{Min(r.A, other.Begin()), Max(r.B, other.End())}
	} else {
		return Region{Max(r.A, other.End()), Min(r.B, other.Begin())}
	}
}

// Clips this Region against the Region provided in the argument.
// That would be if any part of this region is inside of the
// region specified by the argument, that part of the region
// is removed from this region.
func (r Region) Clip(other Region) (ret Region) {
	if other.Covers(r) {
		// this region is a subregion within the other region
		return r
	}
	ret.A, ret.B = r.Begin(), r.End()
	other.A, other.B = other.Begin(), other.End()

	if ret.A >= other.A && ret.A < other.B {
		ret.A = other.B
	}
	if ret.B >= other.A && ret.B <= other.B {
		ret.B = other.A
	}
	if ret.B < ret.A {
		ret.B = ret.A
	}
	return
}

// Cuts away the parts of the region that is in the argument region.
// This is similar to Clip, except that the result can be multiple
// regions.
func (r Region) Cut(other Region) (ret []Region) {
	if r.Contains(other.A) {
		ret = append(ret, Region{r.A, other.A})
	}
	if r.Contains(other.B) {
		ret = append(ret, Region{other.B, r.B})
	}
	if len(ret) == 0 && !other.Covers(r) {
		ret = append(ret, r)
	}
	return
}

// Returns whether the two regions intersects or not
func (r Region) Intersects(other Region) bool {
	return r == other || r.Intersection(other).Size() > 0
}

// Returns the Region that is the intersection of the two
// regions given
func (r Region) Intersection(other Region) (ret Region) {
	if !r.Contains(other.Begin()) && !other.Contains(r.Begin()) {
		return
	}
	r2 := Region{Max(r.Begin(), other.Begin()), Min(r.End(), other.End())}
	if r2.Size() != 0 {
		ret = r2
	}
	return
}

// Adjusts the region in place for the given position and delta
func (r *Region) Adjust(position, delta int) {
	if r.A >= position {
		r.A += delta
	} else if diff := position + delta - r.A; diff < 0 {
		r.A += diff
	}
	if r.B >= position {
		r.B += delta
	} else if diff := position + delta - r.B; diff < 0 {
		r.B += diff
	}
}
<|endoftext|>


<commit_before>//The MIT License (MIT)

//Copyright (c) 2014 Ali Najafizadeh

//Permission is hereby granted, free of charge, to any person obtaining a copy of
//this software and associated documentation files (the "Software"), to deal in
//the Software without restriction, including without limitation the rights to
//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
//the Software, and to permit persons to whom the Software is furnished to do so,
//subject to the following conditions:

//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
//FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
//COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
//IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package relax

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"strings"
)

var lookFor = []string{"{", "}", ":number", ":string"}
var replaceWith = []string{"(?P<", ">", "[0-9\\.]+)", "[0-9a-zA-Z_]+)"}

func compileactualURL(actualURL string) (*regexp.Regexp, string) {
	for index := range lookFor {
		actualURL = strings.Replace(actualURL, lookFor[index], replaceWith[index], -1)
	}
	actualURL = "^" + actualURL + "$"
	r, _ := regexp.Compile(actualURL)

	return r, actualURL
}

func applyPath(target string, source *regexp.Regexp) *map[string]string {
	result := make(map[string]string)
	if source.MatchString(target) {
		keys := source.SubexpNames()
		values := source.FindStringSubmatch(target)

		for index, value := range keys {
			if index != 0 {
				result[value] = values[index]
			}
		}
	}
	return &result
}

//RelaxFuncHandler is a exported func for each handler
type RelaxFuncHandler func(req RelaxRequest, res RelaxResponse)

//RelaxHandler is a structure for storing each handler for each regular expression
type RelaxHandler struct {
	method      string
	path        *regexp.Regexp
	funcHandler RelaxFuncHandler
}

//RelaxRequest is a structure that tries to map the params and send it to RelaxFuncHandler as a first argument
type RelaxRequest struct {
	params  *map[string]string
	Request *http.Request
}

//Param gets the requested param
func (rr *RelaxRequest) Param(name string) string {
	param, _ := (*rr.params)[name]
	return param
}

//RelaxResponse is a structure that wrapps http.ResponseWriter and send it to RelaxFuncHandler as a second argument
type RelaxResponse struct {
	responseWriter http.ResponseWriter
}

//Send is a method that does 2 things set http status code and write the body to the http pipe
func (rr *RelaxResponse) Send(body string, code int) {
	rr.responseWriter.WriteHeader(code)
	fmt.Fprintf(rr.responseWriter, body)
}

//SendAsJSON is extacly as Send method except, ti convert the body message into json.
func (rr *RelaxResponse) SendAsJSON(body interface{}, code int) {
	result, _ := json.Marshal(body)
	temp := string(result)
	rr.Send(temp, code)
}

//Relax structure holds all the registered relax handlers.
type Relax struct {
	relaxHandlerMap map[string]*RelaxHandler
}

func (r *Relax) mainHandler(w http.ResponseWriter, req *http.Request) {
	var statusCode = http.StatusNotFound
	var relaxHandler *RelaxHandler

	url := req.URL
	method := req.Method
	relaxResponse := RelaxResponse{w}

	for _, value := range r.relaxHandlerMap {
		if value.path.MatchString(url.Path) {
			if value.method == method {
				relaxHandler = value
				statusCode = http.StatusOK
			} else {
				statusCode = http.StatusMethodNotAllowed
			}
			break
		}
	}

	if relaxHandler != nil && statusCode == http.StatusOK {
		params := applyPath(url.Path, relaxHandler.path)
		relaxHandler.funcHandler(RelaxRequest{params, req}, relaxResponse)
	} else {
		var errorMessage string
		if statusCode == http.StatusNotFound {
			errorMessage = "Not Found"
		} else if statusCode == http.StatusMethodNotAllowed {
			errorMessage = "Method Not Allowed"
		}

		relaxResponse.Send(errorMessage, statusCode)
	}
}

//RegisterHandler registers handlers for each REST API. if method + path is not unique it returns false.
func (r Relax) RegisterHandler(method string, path string, funcHandler RelaxFuncHandler) bool {
	regexpPath, actualPath := compileactualURL(path)

	if value, ok := r.relaxHandlerMap[actualPath]; ok && value.method == method {
		return false
	}

	r.relaxHandlerMap[actualPath] = &RelaxHandler{method, regexpPath, funcHandler}
	return true
}

//Listen starts listening to requested host and port.
func (r Relax) Listen(host string, port int) {
	http.HandleFunc("/", r.mainHandler)
	http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil)
}

//NewRelax creates Relax structure
func NewRelax() *Relax {
	relax := Relax{}

	relax.relaxHandlerMap = make(map[string]*RelaxHandler)

	return &relax
}
<commit_msg>added query string into RelaxRequest<commit_after>//The MIT License (MIT)

//Copyright (c) 2014 Ali Najafizadeh

//Permission is hereby granted, free of charge, to any person obtaining a copy of
//this software and associated documentation files (the "Software"), to deal in
//the Software without restriction, including without limitation the rights to
//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
//the Software, and to permit persons to whom the Software is furnished to do so,
//subject to the following conditions:

//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
//FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
//COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
//IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package relax

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"strings"
)

var lookFor = []string{"{", "}", ":number", ":string"}
var replaceWith = []string{"(?P<", ">", "[0-9\\.]+)", "[0-9a-zA-Z_]+)"}

func compileactualURL(actualURL string) (*regexp.Regexp, string) {
	for index := range lookFor {
		actualURL = strings.Replace(actualURL, lookFor[index], replaceWith[index], -1)
	}
	actualURL = "^" + actualURL + "$"
	r, _ := regexp.Compile(actualURL)

	return r, actualURL
}

func applyPath(target string, source *regexp.Regexp) *map[string]string {
	result := make(map[string]string)
	if source.MatchString(target) {
		keys := source.SubexpNames()
		values := source.FindStringSubmatch(target)

		for index, value := range keys {
			if index != 0 {
				result[value] = values[index]
			}
		}
	}
	return &result
}

//RelaxFuncHandler is a exported func for each handler
type RelaxFuncHandler func(req RelaxRequest, res RelaxResponse)

//RelaxHandler is a structure for storing each handler for each regular expression
type RelaxHandler struct {
	method      string
	path        *regexp.Regexp
	funcHandler RelaxFuncHandler
}

//RelaxRequest is a structure that tries to map the params and send it to RelaxFuncHandler as a first argument
type RelaxRequest struct {
	params  *map[string]string
	query   url.Values
	Request *http.Request
}

//Param gets the requested param
func (rr *RelaxRequest) Param(name string) string {
	param, _ := (*rr.params)[name]
	return param
}

//Query gets the querystring value
func (rr *RelaxRequest) Query(name string) string {
	return rr.query.Get(name)
}

//RelaxResponse is a structure that wrapps http.ResponseWriter and send it to RelaxFuncHandler as a second argument
type RelaxResponse struct {
	responseWriter http.ResponseWriter
}

//Send is a method that does 2 things set http status code and write the body to the http pipe
func (rr *RelaxResponse) Send(body string, code int) {
	rr.responseWriter.WriteHeader(code)
	fmt.Fprintf(rr.responseWriter, body)
}

//SendAsJSON is extacly as Send method except, ti convert the body message into json.
func (rr *RelaxResponse) SendAsJSON(body interface{}, code int) {
	result, _ := json.Marshal(body)
	temp := string(result)
	rr.Send(temp, code)
}

//Relax structure holds all the registered relax handlers.
type Relax struct {
	relaxHandlerMap map[string]*RelaxHandler
}

func (r *Relax) mainHandler(w http.ResponseWriter, req *http.Request) {
	var statusCode = http.StatusNotFound
	var relaxHandler *RelaxHandler

	url := req.URL
	method := req.Method
	relaxResponse := RelaxResponse{w}

	for _, value := range r.relaxHandlerMap {
		if value.path.MatchString(url.Path) {
			if value.method == method {
				relaxHandler = value
				statusCode = http.StatusOK
			} else {
				statusCode = http.StatusMethodNotAllowed
			}
			break
		}
	}

	if relaxHandler != nil && statusCode == http.StatusOK {
		params := applyPath(url.Path, relaxHandler.path)
		query := url.Query()
		relaxHandler.funcHandler(RelaxRequest{params, query, req}, relaxResponse)
	} else {
		var errorMessage string
		if statusCode == http.StatusNotFound {
			errorMessage = "Not Found"
		} else if statusCode == http.StatusMethodNotAllowed {
			errorMessage = "Method Not Allowed"
		}

		relaxResponse.Send(errorMessage, statusCode)
	}
}

//RegisterHandler registers handlers for each REST API. if method + path is not unique it returns false.
func (r Relax) RegisterHandler(method string, path string, funcHandler RelaxFuncHandler) bool {
	regexpPath, actualPath := compileactualURL(path)

	if value, ok := r.relaxHandlerMap[actualPath]; ok && value.method == method {
		return false
	}

	r.relaxHandlerMap[actualPath] = &RelaxHandler{method, regexpPath, funcHandler}
	return true
}

//Listen starts listening to requested host and port.
func (r Relax) Listen(host string, port int) {
	http.HandleFunc("/", r.mainHandler)
	http.ListenAndServe(fmt.Sprintf("%s:%d", host, port), nil)
}

//NewRelax creates Relax structure
func NewRelax() *Relax {
	relax := Relax{}

	relax.relaxHandlerMap = make(map[string]*RelaxHandler)

	return &relax
}
<|endoftext|>


<commit_before>package termui

import (
	"github.com/nsf/termbox-go"
)

var rootrenderer = Renderer{0, 0, nil, termbox.ColorDefault, termbox.ColorDefault}

// Renderer helps drawing an element
type Renderer struct {
	x, y   int
	cur    Element
	fg, bg termbox.Attribute
}

// Set the given rune at a relative x and y position
func (r Renderer) Set(x, y int, ch rune) {
	termbox.SetCell(x+r.x, y+r.y, ch, r.fg, r.bg)
}

// SetAttr sets the given rune at a relative x and y position and applys the attribute to the foreground.
// This can be used to invert or underline a cell.
func (r Renderer) SetAttr(x, y int, ch rune, attr termbox.Attribute) {
	termbox.SetCell(x+r.x, y+r.y, ch, r.fg|attr, r.bg)
}

// RenderChild draws the given child.
func (r Renderer) RenderChild(e Element, width, height, xOffset, yOffset int) {
	elW, elH := e.Width(), e.Height()

	gravity := GravityProperty.Get(e)
	fg := ForegroundProperty.Get(e)
	bg := BackgroundProperty.Get(e)

	switch gravity & horizontal {
	case Left, Left | Right:
		xOffset += 0
	case Right:
		xOffset += width - elW
	case NoGravity:
		xOffset += (width - elW) / 2
	}
	switch gravity & vertical {
	case Top, Top | Bottom:
		yOffset += 0
	case Bottom:
		yOffset += height - elH
	case NoGravity:
		yOffset += (height - elH) / 2
	}

	e.Render(Renderer{
		x:  r.x + xOffset,
		y:  r.y + yOffset,
		fg: fg, bg: bg,
	})
}
<commit_msg>fill child area with background color<commit_after>package termui

import (
	"github.com/nsf/termbox-go"
)

var rootrenderer = Renderer{0, 0, nil, termbox.ColorDefault, termbox.ColorDefault}

// Renderer helps drawing an element
type Renderer struct {
	x, y   int
	cur    Element
	fg, bg termbox.Attribute
}

// Set the given rune at a relative x and y position
func (r Renderer) Set(x, y int, ch rune) {
	termbox.SetCell(x+r.x, y+r.y, ch, r.fg, r.bg)
}

// SetAttr sets the given rune at a relative x and y position and applys the attribute to the foreground.
// This can be used to invert or underline a cell.
func (r Renderer) SetAttr(x, y int, ch rune, attr termbox.Attribute) {
	termbox.SetCell(x+r.x, y+r.y, ch, r.fg|attr, r.bg)
}

// RenderChild draws the given child.
func (r Renderer) RenderChild(e Element, width, height, xOffset, yOffset int) {
	elW, elH := e.Width(), e.Height()

	gravity := GravityProperty.Get(e)
	fg := ForegroundProperty.Get(e)
	bg := BackgroundProperty.Get(e)

	for x := xOffset; x < xOffset+width; x++ {
		for y := yOffset; y < yOffset+height; y++ {
			r.Set(x, y, ' ')
		}
	}

	switch gravity & horizontal {
	case Left, Left | Right:
		xOffset += 0
	case Right:
		xOffset += width - elW
	case NoGravity:
		xOffset += (width - elW) / 2
	}
	switch gravity & vertical {
	case Top, Top | Bottom:
		yOffset += 0
	case Bottom:
		yOffset += height - elH
	case NoGravity:
		yOffset += (height - elH) / 2
	}

	e.Render(Renderer{
		x:  r.x + xOffset,
		y:  r.y + yOffset,
		fg: fg, bg: bg,
	})
}
<|endoftext|>


<commit_before>// ReqManager is the gocui manager for requestors.
package goublu

import (
	"fmt"
	"github.com/jwoehr/gocui"
	"strings"
)

// A gocui manager for Requestors.
type ReqManager struct {
	UM         *UbluManager
	G          *gocui.Gui
	X          int
	Y          int
	Title      string
	BgColor    gocui.Attribute
	FgColor    gocui.Attribute
	ReqEditor  gocui.Editor
	Text       string
	UbluinBuf  string
	UbluoutBuf string
}

// Instances a new manager.
func NewReqManager(um *UbluManager, g *gocui.Gui, x int, y int, title string, bgc gocui.Attribute, fgc gocui.Attribute, text string) (rm *ReqManager) {
	rm = &ReqManager{
		UM:      um,
		G:       g,
		X:       x,
		Y:       y,
		Title:   title,
		BgColor: bgc,
		FgColor: fgc,
		Text:    text,
	}
	rm.ReqEditor = gocui.EditorFunc(func(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
		gx, gy := rm.G.Size()
		cx, cy := v.Cursor()

		// Shut up compiler
		gx = gx
		gy = gy
		cx = cx
		cy = cy

		switch {
		case key == gocui.KeyArrowDown:
			v.MoveCursor(0, 1, false)
		case key == gocui.KeyArrowUp:
			v.MoveCursor(0, -1, false)
		case key == gocui.KeyArrowLeft:
			v.MoveCursor(-1, 0, false)
		case key == gocui.KeyArrowRight:
			v.MoveCursor(1, 0, false)
		case key == gocui.KeyPgup:
			ox, oy := v.Origin()
			v.SetOrigin(ox, oy-20)
		case key == gocui.KeyPgdn:
			ox, oy := v.Origin()
			v.SetOrigin(ox, oy+20)
		/*
			case key == gocui.MouseWheelUp:
				v.MoveCursor(0, -1, false)
				case key == gocui.MouseWheelDown:
				v.MoveCursor(0, 1, false)
		*/
		case key == gocui.KeyF3:
			rm.EndReq()
		}
	})

	return rm
}

func (rm *ReqManager) calcPos(maxX int, maxY int) (x1 int, y1 int, x2 int, y2 int) {
	x1 = Max((maxX-rm.X)/2, 0)
	x2 = maxX - x1
	y1 = Max((maxY-rm.Y)/2, 0)
	y2 = maxY - y1
	return x1, y1, x2, y2
}

// Unshows the requestor.
func (rm *ReqManager) EndReq() {
	rm.G.SetManager(rm.UM)
	rm.UM.Layout(rm.G)
	v, _ := rm.G.View("Ubluin")
	v.Clear()
	for _, ch := range strings.Trim(strings.TrimSpace(rm.UbluinBuf), "\000") {
		v.EditWrite(ch)
	}
	v, _ = rm.G.View("Ubluout")
	fmt.Fprintf(v, "%s\n", strings.Trim(strings.TrimSpace(rm.UbluoutBuf), "\000"))
}

// Shows the requestor.
func (rm *ReqManager) StartReq() {
	v, _ := rm.G.View("Ubluin")
	rm.UbluinBuf = v.Buffer()
	v, _ = rm.G.View("Ubluout")
	rm.UbluoutBuf = v.Buffer()
	rm.G.SetManager(rm.UM, rm)
}

// Obligatory layout redraw function
func (rm *ReqManager) Layout(g *gocui.Gui) error {
	x1, y1, x2, y2 := rm.calcPos(g.Size())
	if v, err := g.SetView(rm.Title, x1, y1, x2, y2); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.Title = " " + rm.Title + " "
		v.Editable = true
		v.Editor = rm.ReqEditor
		v.Wrap = true
		v.BgColor = rm.BgColor
		v.FgColor = rm.FgColor
		fmt.Fprintf(v, "%s", rm.Text)
	}
	if _, err := g.SetCurrentView(rm.Title); err != nil {
		return err
	}
	return nil
}
<commit_msg>better paging<commit_after>// ReqManager is the gocui manager for requestors.
package goublu

import (
	"fmt"
	"github.com/jwoehr/gocui"
	"strings"
)

// A gocui manager for Requestors.
type ReqManager struct {
	UM         *UbluManager
	G          *gocui.Gui
	X          int
	Y          int
	Title      string
	BgColor    gocui.Attribute
	FgColor    gocui.Attribute
	ReqEditor  gocui.Editor
	Text       string
	UbluinBuf  string
	UbluoutBuf string
}

// Instances a new manager.
func NewReqManager(um *UbluManager, g *gocui.Gui, x int, y int, title string, bgc gocui.Attribute, fgc gocui.Attribute, text string) (rm *ReqManager) {
	rm = &ReqManager{
		UM:      um,
		G:       g,
		X:       x,
		Y:       y,
		Title:   title,
		BgColor: bgc,
		FgColor: fgc,
		Text:    text,
	}
	rm.ReqEditor = gocui.EditorFunc(func(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) {
		gx, gy := rm.G.Size()
		cx, cy := v.Cursor()
		_, y1, _, y2 := rm.calcPos(gx, gy)
		pgHeight := y2 - y1

		// Shut up compiler
		gx = gx
		gy = gy
		cx = cx
		cy = cy

		switch {
		case key == gocui.KeyArrowDown:
			v.MoveCursor(0, 1, false)
		case key == gocui.KeyArrowUp:
			v.MoveCursor(0, -1, false)
		case key == gocui.KeyArrowLeft:
			v.MoveCursor(-1, 0, false)
		case key == gocui.KeyArrowRight:
			v.MoveCursor(1, 0, false)
		case key == gocui.KeyPgup:
			ox, oy := v.Origin()
			v.SetOrigin(ox, Max(0, oy-(pgHeight-1)))
		case key == gocui.KeyPgdn:
			ox, oy := v.Origin()
			v.SetOrigin(ox, oy+(pgHeight-1))
		/*
			case key == gocui.MouseWheelUp:
				v.MoveCursor(0, -1, false)
				case key == gocui.MouseWheelDown:
				v.MoveCursor(0, 1, false)
		*/
		case key == gocui.KeyF3:
			rm.EndReq()
		}
	})

	return rm
}

func (rm *ReqManager) calcPos(maxX int, maxY int) (x1 int, y1 int, x2 int, y2 int) {
	x1 = Max((maxX-rm.X)/2, 0)
	x2 = maxX - x1
	y1 = Max((maxY-rm.Y)/2, 0)
	y2 = maxY - y1
	return x1, y1, x2, y2
}

// Unshows the requestor.
func (rm *ReqManager) EndReq() {
	rm.G.SetManager(rm.UM)
	rm.UM.Layout(rm.G)
	v, _ := rm.G.View("Ubluin")
	v.Clear()
	for _, ch := range strings.Trim(strings.TrimSpace(rm.UbluinBuf), "\000") {
		v.EditWrite(ch)
	}
	v, _ = rm.G.View("Ubluout")
	fmt.Fprintf(v, "%s\n", strings.Trim(strings.TrimSpace(rm.UbluoutBuf), "\000"))
}

// Shows the requestor.
func (rm *ReqManager) StartReq() {
	v, _ := rm.G.View("Ubluin")
	rm.UbluinBuf = v.Buffer()
	v, _ = rm.G.View("Ubluout")
	rm.UbluoutBuf = v.Buffer()
	rm.G.SetManager(rm.UM, rm)
}

// Obligatory layout redraw function
func (rm *ReqManager) Layout(g *gocui.Gui) error {
	x1, y1, x2, y2 := rm.calcPos(g.Size())
	if v, err := g.SetView(rm.Title, x1, y1, x2, y2); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.Title = " " + rm.Title + " "
		v.Editable = true
		v.Editor = rm.ReqEditor
		v.Wrap = true
		v.BgColor = rm.BgColor
		v.FgColor = rm.FgColor
		fmt.Fprintf(v, "%s", rm.Text)
	}
	if _, err := g.SetCurrentView(rm.Title); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


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

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

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

package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"

	"golang.org/x/oauth2"
	"google.golang.org/api/googleapi"
	"google.golang.org/api/youtube/v3"
)

type chanChan chan chan struct{}

var (
	filename       = flag.String("filename", "", "Filename to upload. Can be a URL")
	thumbnail      = flag.String("thumbnail", "", "Thumbnail to upload. Can be a URL")
	caption        = flag.String("caption", "", "Caption to upload. Can be URL")
	title          = flag.String("title", "Video Title", "Video title")
	description    = flag.String("description", "uploaded by youtubeuploader", "Video description")
	language       = flag.String("language", "en", "Video language")
	categoryId     = flag.String("categoryId", "", "Video category Id")
	tags           = flag.String("tags", "", "Comma separated list of video tags")
	privacy        = flag.String("privacy", "private", "Video privacy status")
	quiet          = flag.Bool("quiet", false, "Suppress progress indicator")
	rate           = flag.Int("ratelimit", 0, "Rate limit upload in kbps. No limit by default")
	metaJSON       = flag.String("metaJSON", "", "JSON file containing title,description,tags etc (optional)")
	limitBetween   = flag.String("limitBetween", "", "Only rate limit between these times e.g. 10:00-14:00 (local time zone)")
	headlessAuth   = flag.Bool("headlessAuth", false, "set this if no browser available for the oauth authorisation step")
	oAuthPort      = flag.Int("oAuthPort", 8080, "TCP port to listen on when requesting an oAuth token")
	showAppVersion = flag.Bool("v", false, "show version")
	chunksize      = flag.Int("chunksize", googleapi.DefaultUploadChunkSize, "size (in bytes) of each upload chunk. A zero value will cause all data to be uploaded in a single request")

	// this is set by compile-time to match git tag
	appVersion string = "unknown"
)

func main() {
	flag.Parse()

	if *showAppVersion {
		fmt.Printf("Youtubeuploader version: %s\n", appVersion)
		os.Exit(0)
	}

	if *filename == "" {
		fmt.Printf("You must provide a filename of a video file to upload\n")
		flag.PrintDefaults()
		os.Exit(1)
	}

	var reader io.ReadCloser
	var filesize int64
	var err error

	var limitRange limitRange
	if *limitBetween != "" {
		limitRange, err = parseLimitBetween(*limitBetween)
		if err != nil {
			fmt.Printf("Invalid value for -limitBetween: %v", err)
			os.Exit(1)
		}
	}

	reader, filesize, err = Open(*filename)
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()

	var thumbReader io.ReadCloser
	if *thumbnail != "" {
		thumbReader, _, err = Open(*thumbnail)
		if err != nil {
			log.Fatal(err)
		}
		defer thumbReader.Close()
	}

	var captionReader io.ReadCloser
	if *caption != "" {
		captionReader, _, err = Open(*caption)
		if err != nil {
			log.Fatal(err)
		}
		defer captionReader.Close()
	}

	ctx := context.Background()
	transport := &limitTransport{rt: http.DefaultTransport, lr: limitRange, filesize: filesize}
	ctx = context.WithValue(ctx, oauth2.HTTPClient, &http.Client{
		Transport: transport,
	})

	var quitChan chanChan
	if !*quiet {
		quitChan = make(chanChan)
		go func() {
			Progress(quitChan, transport, filesize)
		}()
	}
	client, err := buildOAuthHTTPClient(ctx, []string{youtube.YoutubeUploadScope, youtube.YoutubepartnerScope, youtube.YoutubeScope})
	if err != nil {
		log.Fatalf("Error building OAuth client: %v", err)
	}

	upload := &youtube.Video{
		Snippet:          &youtube.VideoSnippet{},
		RecordingDetails: &youtube.VideoRecordingDetails{},
		Status:           &youtube.VideoStatus{},
	}

	videoMeta := LoadVideoMeta(*metaJSON, upload)

	service, err := youtube.New(client)
	if err != nil {
		log.Fatalf("Error creating Youtube client: %s", err)
	}

	if upload.Status.PrivacyStatus == "" {
		upload.Status.PrivacyStatus = *privacy
	}
	if upload.Snippet.Tags == nil && strings.Trim(*tags, "") != "" {
		upload.Snippet.Tags = strings.Split(*tags, ",")
	}
	if upload.Snippet.Title == "" {
		upload.Snippet.Title = *title
	}
	if upload.Snippet.Description == "" {
		upload.Snippet.Description = *description
	}
	if upload.Snippet.CategoryId == "" && *categoryId != "" {
		upload.Snippet.CategoryId = *categoryId
	}
	if upload.Snippet.DefaultLanguage == "" && *language != "" {
		upload.Snippet.DefaultLanguage = *language
	}
	if upload.Snippet.DefaultAudioLanguage == "" && *language != "" {
		upload.Snippet.DefaultAudioLanguage = *language
	}

	fmt.Printf("Uploading file '%s'...\n", *filename)

	var option googleapi.MediaOption
	var video *youtube.Video

	option = googleapi.ChunkSize(*chunksize)

	call := service.Videos.Insert("snippet,status,recordingDetails", upload)
	video, err = call.Media(reader, option).Do()

	if quitChan != nil {
		quit := make(chan struct{})
		quitChan <- quit
		<-quit
	}

	if err != nil {
		if video != nil {
			log.Fatalf("Error making YouTube API call: %v, %v", err, video.HTTPStatusCode)
		} else {
			log.Fatalf("Error making YouTube API call: %v", err)
		}
	}
	fmt.Printf("Upload successful! Video ID: %v\n", video.Id)

	if thumbReader != nil {
		log.Printf("Uploading thumbnail '%s'...\n", *thumbnail)
		_, err = service.Thumbnails.Set(video.Id).Media(thumbReader).Do()
		if err != nil {
			log.Fatalf("Error making YouTube API call: %v", err)
		}
		fmt.Printf("Thumbnail uploaded!\n")
	}

	// Insert caption
	if captionReader != nil {
		captionObj := &youtube.Caption{
			Snippet: &youtube.CaptionSnippet{},
		}
		captionObj.Snippet.VideoId = video.Id
		captionObj.Snippet.Language = *language
		captionObj.Snippet.Name = *language
		captionInsert := service.Captions.Insert("snippet", captionObj).Sync(true)
		captionRes, err := captionInsert.Media(captionReader).Do()
		if err != nil {
			if captionRes != nil {
				log.Fatalf("Error inserting caption: %v, %v", err, captionRes.HTTPStatusCode)
			} else {
				log.Fatalf("Error inserting caption: %v", err)
			}
		}
		fmt.Printf("Caption uploaded!\n")
	}

	plx := &Playlistx{}
	if upload.Status.PrivacyStatus != "" {
		plx.PrivacyStatus = upload.Status.PrivacyStatus
	}
	// PlaylistID is deprecated in favour of PlaylistIDs
	if videoMeta.PlaylistID != "" {
		plx.Id = videoMeta.PlaylistID
		err = plx.AddVideoToPlaylist(service, video.Id)
		if err != nil {
			log.Fatalf("Error adding video to playlist: %s", err)
		}
	}

	if len(videoMeta.PlaylistIDs) > 0 {
		plx.Title = ""
		for _, pid := range videoMeta.PlaylistIDs {
			plx.Id = pid
			err = plx.AddVideoToPlaylist(service, video.Id)
			if err != nil {
				log.Fatalf("Error adding video to playlist: %s", err)
			}
		}
	}

	if len(videoMeta.PlaylistTitles) > 0 {
		plx.Id = ""
		for _, title := range videoMeta.PlaylistTitles {
			plx.Title = title
			err = plx.AddVideoToPlaylist(service, video.Id)
			if err != nil {
				log.Fatalf("Error adding video to playlist: %s", err)
			}
		}
	}
}
<commit_msg>Add notify subscribers flag<commit_after>/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"

	"golang.org/x/oauth2"
	"google.golang.org/api/googleapi"
	"google.golang.org/api/youtube/v3"
)

type chanChan chan chan struct{}

var (
	filename          = flag.String("filename", "", "Filename to upload. Can be a URL")
	thumbnail         = flag.String("thumbnail", "", "Thumbnail to upload. Can be a URL")
	caption           = flag.String("caption", "", "Caption to upload. Can be URL")
	title             = flag.String("title", "Video Title", "Video title")
	description       = flag.String("description", "uploaded by youtubeuploader", "Video description")
	language          = flag.String("language", "en", "Video language")
	categoryId        = flag.String("categoryId", "", "Video category Id")
	tags              = flag.String("tags", "", "Comma separated list of video tags")
	privacy           = flag.String("privacy", "private", "Video privacy status")
	quiet             = flag.Bool("quiet", false, "Suppress progress indicator")
	rate              = flag.Int("ratelimit", 0, "Rate limit upload in kbps. No limit by default")
	metaJSON          = flag.String("metaJSON", "", "JSON file containing title,description,tags etc (optional)")
	limitBetween      = flag.String("limitBetween", "", "Only rate limit between these times e.g. 10:00-14:00 (local time zone)")
	headlessAuth      = flag.Bool("headlessAuth", false, "set this if no browser available for the oauth authorisation step")
	oAuthPort         = flag.Int("oAuthPort", 8080, "TCP port to listen on when requesting an oAuth token")
	showAppVersion    = flag.Bool("v", false, "show version")
	chunksize         = flag.Int("chunksize", googleapi.DefaultUploadChunkSize, "size (in bytes) of each upload chunk. A zero value will cause all data to be uploaded in a single request")
	notifySubscribers = flag.Bool("notify", true, "notify channel subscribers of new video")

	// this is set by compile-time to match git tag
	appVersion string = "unknown"
)

func main() {
	flag.Parse()

	if *showAppVersion {
		fmt.Printf("Youtubeuploader version: %s\n", appVersion)
		os.Exit(0)
	}

	if *filename == "" {
		fmt.Printf("You must provide a filename of a video file to upload\n")
		flag.PrintDefaults()
		os.Exit(1)
	}

	var reader io.ReadCloser
	var filesize int64
	var err error

	var limitRange limitRange
	if *limitBetween != "" {
		limitRange, err = parseLimitBetween(*limitBetween)
		if err != nil {
			fmt.Printf("Invalid value for -limitBetween: %v", err)
			os.Exit(1)
		}
	}

	reader, filesize, err = Open(*filename)
	if err != nil {
		log.Fatal(err)
	}
	defer reader.Close()

	var thumbReader io.ReadCloser
	if *thumbnail != "" {
		thumbReader, _, err = Open(*thumbnail)
		if err != nil {
			log.Fatal(err)
		}
		defer thumbReader.Close()
	}

	var captionReader io.ReadCloser
	if *caption != "" {
		captionReader, _, err = Open(*caption)
		if err != nil {
			log.Fatal(err)
		}
		defer captionReader.Close()
	}

	ctx := context.Background()
	transport := &limitTransport{rt: http.DefaultTransport, lr: limitRange, filesize: filesize}
	ctx = context.WithValue(ctx, oauth2.HTTPClient, &http.Client{
		Transport: transport,
	})

	var quitChan chanChan
	if !*quiet {
		quitChan = make(chanChan)
		go func() {
			Progress(quitChan, transport, filesize)
		}()
	}
	client, err := buildOAuthHTTPClient(ctx, []string{youtube.YoutubeUploadScope, youtube.YoutubepartnerScope, youtube.YoutubeScope})
	if err != nil {
		log.Fatalf("Error building OAuth client: %v", err)
	}

	upload := &youtube.Video{
		Snippet:          &youtube.VideoSnippet{},
		RecordingDetails: &youtube.VideoRecordingDetails{},
		Status:           &youtube.VideoStatus{},
	}

	videoMeta := LoadVideoMeta(*metaJSON, upload)

	service, err := youtube.New(client)
	if err != nil {
		log.Fatalf("Error creating Youtube client: %s", err)
	}

	if upload.Status.PrivacyStatus == "" {
		upload.Status.PrivacyStatus = *privacy
	}
	if upload.Snippet.Tags == nil && strings.Trim(*tags, "") != "" {
		upload.Snippet.Tags = strings.Split(*tags, ",")
	}
	if upload.Snippet.Title == "" {
		upload.Snippet.Title = *title
	}
	if upload.Snippet.Description == "" {
		upload.Snippet.Description = *description
	}
	if upload.Snippet.CategoryId == "" && *categoryId != "" {
		upload.Snippet.CategoryId = *categoryId
	}
	if upload.Snippet.DefaultLanguage == "" && *language != "" {
		upload.Snippet.DefaultLanguage = *language
	}
	if upload.Snippet.DefaultAudioLanguage == "" && *language != "" {
		upload.Snippet.DefaultAudioLanguage = *language
	}

	fmt.Printf("Uploading file '%s'...\n", *filename)

	var option googleapi.MediaOption
	var video *youtube.Video

	option = googleapi.ChunkSize(*chunksize)

	call := service.Videos.Insert("snippet,status,recordingDetails", upload)
	video, err = call.NotifySubscribers(*notifySubscribers).Media(reader, option).Do()

	if quitChan != nil {
		quit := make(chan struct{})
		quitChan <- quit
		<-quit
	}

	if err != nil {
		if video != nil {
			log.Fatalf("Error making YouTube API call: %v, %v", err, video.HTTPStatusCode)
		} else {
			log.Fatalf("Error making YouTube API call: %v", err)
		}
	}
	fmt.Printf("Upload successful! Video ID: %v\n", video.Id)

	if thumbReader != nil {
		log.Printf("Uploading thumbnail '%s'...\n", *thumbnail)
		_, err = service.Thumbnails.Set(video.Id).Media(thumbReader).Do()
		if err != nil {
			log.Fatalf("Error making YouTube API call: %v", err)
		}
		fmt.Printf("Thumbnail uploaded!\n")
	}

	// Insert caption
	if captionReader != nil {
		captionObj := &youtube.Caption{
			Snippet: &youtube.CaptionSnippet{},
		}
		captionObj.Snippet.VideoId = video.Id
		captionObj.Snippet.Language = *language
		captionObj.Snippet.Name = *language
		captionInsert := service.Captions.Insert("snippet", captionObj).Sync(true)
		captionRes, err := captionInsert.Media(captionReader).Do()
		if err != nil {
			if captionRes != nil {
				log.Fatalf("Error inserting caption: %v, %v", err, captionRes.HTTPStatusCode)
			} else {
				log.Fatalf("Error inserting caption: %v", err)
			}
		}
		fmt.Printf("Caption uploaded!\n")
	}

	plx := &Playlistx{}
	if upload.Status.PrivacyStatus != "" {
		plx.PrivacyStatus = upload.Status.PrivacyStatus
	}
	// PlaylistID is deprecated in favour of PlaylistIDs
	if videoMeta.PlaylistID != "" {
		plx.Id = videoMeta.PlaylistID
		err = plx.AddVideoToPlaylist(service, video.Id)
		if err != nil {
			log.Fatalf("Error adding video to playlist: %s", err)
		}
	}

	if len(videoMeta.PlaylistIDs) > 0 {
		plx.Title = ""
		for _, pid := range videoMeta.PlaylistIDs {
			plx.Id = pid
			err = plx.AddVideoToPlaylist(service, video.Id)
			if err != nil {
				log.Fatalf("Error adding video to playlist: %s", err)
			}
		}
	}

	if len(videoMeta.PlaylistTitles) > 0 {
		plx.Id = ""
		for _, title := range videoMeta.PlaylistTitles {
			plx.Title = title
			err = plx.AddVideoToPlaylist(service, video.Id)
			if err != nil {
				log.Fatalf("Error adding video to playlist: %s", err)
			}
		}
	}
}
<|endoftext|>