<commit_before>package checks

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

const (
	daemonDNSEndpoint = "daemon.ose-mon-a.endpoints.cluster.local"
	daemonDNSServiceA = "daemon.ose-mon-a.svc.cluster.local"
	daemonDNSServiceB = "daemon.ose-mon-b.svc.cluster.local"
	daemonDNSServiceC = "daemon.ose-mon-c.svc.cluster.local"
	daemonDNSPod      = "daemon"
	kubernetesIP      = "172.30.0.1"
)

var num = regexp.MustCompile(`\d+(?:\.\d+)?`)

func CheckExternalSystem(url string) error {
	if err := checkHttp(url); err != nil {
		msg := "Call to " + url + " failed"
		log.Println(msg)
		return errors.New(msg)
	}

	return nil
}

func CheckChrony() error {
	log.Println("Checking output of 'chronyc tracking'")

	out, err := exec.Command("bash", "-c", "chronyc tracking").Output()
	if err != nil {
		msg := "Could not check chrony status: " + err.Error()
		log.Println(msg)
		return errors.New(msg)
	}

	offset, err := parseChronyOffset(string(out))

	if offset < -100 || offset > 100 {
		return errors.New("Time is not correct on the server or chrony is not running")
	} else {
		return nil
	}
}

func parseChronyOffset(out string) (float64, error) {
	for _, line := range strings.Split(string(out), "\n") {
		if strings.Contains(line, "Last offset") {
			// Example output
			// Reference ID    : 0A7CD814 (bn-ntp-01.sbb.ch)
			// Stratum         : 2
			// Ref time (UTC)  : Thu May 31 13:41:40 2018
			// System time     : 0.000037743 seconds fast of NTP time
			// Last offset     : +0.000061081 seconds
			// RMS offset      : 0.000333012 seconds
			// Frequency       : 6.629 ppm fast
			// Residual freq   : +0.004 ppm
			// Skew            : 0.140 ppm
			// Root delay      : 0.002649408 seconds
			// Root dispersion : 0.000559144 seconds
			// Update interval : 517.4 seconds
			// Leap status     : Normal
			rgx := regexp.MustCompile("(.*offset\\s+:\\s+)(.*?)\\s+seconds")
			offset := rgx.FindStringSubmatch(line)

			log.Println("Found chrony offset:", offset[2])
			out, err := strconv.ParseFloat(offset[2], 64)
			if err != nil {
				return -1000, fmt.Errorf("couldn't parse chrony offset. Value was %v", offset[2])
			}
			return out, nil
		}
	}
	return -1000, fmt.Errorf("couldn't parse chrony offset. Offset line was not found.")
}

func CheckNtpd() error {
	log.Println("Checking output of 'ntpq -c rv 0 offset'")

	out, err := exec.Command("bash", "-c", "ntpq -c rv 0 offset").Output()
	if err != nil {
		msg := "Could not check ntpd status: " + err.Error()
		log.Println(msg)
		return errors.New(msg)
	}

	offset, err := parseNTPOffsetFromNTPD(string(out))

	if offset < -100 || offset > 100 {
		return errors.New("Time is not correct on the server or ntpd is not running")
	} else {
		return nil
	}
}

func parseNTPOffsetFromNTPD(out string) (float64, error) {
	for _, l := range strings.Split(string(out), "\n") {
		if strings.Contains(l, "offset") {
			// Example output
			// mintc=3, offset=0.400, frequency=-4.546, sys_jitter=1.015,
			// tc=10, mintc=3, offset=-0.648, frequency=3.934, sys_jitter=0.253,
			rgx := regexp.MustCompile("(.*offset=)(.*?),")
			offset := rgx.FindStringSubmatch(l)

			log.Println("Found ntpd offset:", offset[2])
			out, err := strconv.ParseFloat(offset[2], 64)
			if err != nil {
				return -1000, fmt.Errorf("couldn't parse ntp offset. Value was %v", offset[2])
			}
			return out, nil
		}
	}
	return -1000, fmt.Errorf("couldn't parse ntp offset. Offset line was not found.")
}

func getIpsForName(n string) []net.IP {
	ips, err := net.LookupIP(n)
	if err != nil {
		log.Println("failed to lookup ip for name ", n)
		return nil
	}
	return ips
}

func checkHttp(toCall string) error {
	log.Println("Checking access to:", toCall)
	if strings.HasPrefix(toCall, "https") {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
		client := &http.Client{Transport: tr}
		resp, err := client.Get(toCall)
		if err != nil {
			log.Println("error in http check: ", err)
			return err
		} else {
			resp.Body.Close()
			return nil
		}
	} else {
		resp, err := http.Get(toCall)
		if err != nil {
			log.Println("error in http check: ", err)
			return err
		} else {
			resp.Body.Close()
			return nil
		}
	}
}

func getEndpoint(slow bool) string {
	if slow {
		return "slow"
	} else {
		return "fast"
	}
}

// isVgSizeOk returns true if vgs output in stdOut indicates that the volume
// group free space is equal or above the percentage treshold okSize, which is
// expected to be in the range [0, 100].
func isVgSizeOk(stdOut string, okSize int) bool {
	// Example
	// 5.37 26.84 vg_fast_registry
	// 5.37 26.84 vg_slow
	nums := num.FindAllString(stdOut, 2)

	if len(nums) != 2 {
		log.Println("Unable to parse vgs output:", stdOut)
		return false
	}

	free, err := strconv.ParseFloat(nums[0], 64)
	if err != nil {
		log.Println("Unable to parse first digit of output", stdOut)
		return false
	}
	size, err := strconv.ParseFloat(nums[1], 64)
	if err != nil {
		log.Println("Unable to parse second digit of output", stdOut)
		return false
	}

	// calculate usage
	if 100/size*free < float64(okSize) {
		msg := fmt.Sprintf("VG free size is below treshold. Size: %v, free: %v, treshold: %v %%", size, free, okSize)
		log.Println(msg)
		return false
	}

	return true
}

// isLvsSizeOk returns true if lvs output in stdOut indicates that the logical
// volume percentage full for data and metadata are both below the threshold
// okSize, which is expected to be in the range [0, 100].
func isLvsSizeOk(stdOut string, okSize int) bool {
	// Examples
	// 42.10  8.86   docker-pool
	// 13.63  8.93   lv_fast_registry_pool
	checksOk := 0
	for _, nr := range num.FindAllString(stdOut, -1) {
		i, err := strconv.ParseFloat(nr, 64)
		if err != nil {
			log.Print("Unable to parse int:", nr)
			return false
		}

		if i < float64(okSize) {
			checksOk++
		} else {
			log.Println("LVM pool size exceeded okSize:", i)
		}
	}

	return checksOk == 2
}
<commit_msg>From 100 seconds to 100 milliseconds for chrony offset check.<commit_after>package checks

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

const (
	daemonDNSEndpoint = "daemon.ose-mon-a.endpoints.cluster.local"
	daemonDNSServiceA = "daemon.ose-mon-a.svc.cluster.local"
	daemonDNSServiceB = "daemon.ose-mon-b.svc.cluster.local"
	daemonDNSServiceC = "daemon.ose-mon-c.svc.cluster.local"
	daemonDNSPod      = "daemon"
	kubernetesIP      = "172.30.0.1"
)

var num = regexp.MustCompile(`\d+(?:\.\d+)?`)

func CheckExternalSystem(url string) error {
	if err := checkHttp(url); err != nil {
		msg := "Call to " + url + " failed"
		log.Println(msg)
		return errors.New(msg)
	}

	return nil
}

func CheckChrony() error {
	log.Println("Checking output of 'chronyc tracking'")

	out, err := exec.Command("bash", "-c", "chronyc tracking").Output()
	if err != nil {
		msg := "Could not check chrony status: " + err.Error()
		log.Println(msg)
		return errors.New(msg)
	}

	offset, err := parseChronyOffset(string(out))

	if offset < -0.1 || offset > 0.1 { // 100 Millisekunden
		return errors.New("Time is not correct on the server or chrony is not running")
	} else {
		return nil
	}
}

func parseChronyOffset(out string) (float64, error) {
	for _, line := range strings.Split(string(out), "\n") {
		if strings.Contains(line, "Last offset") {
			// Example output
			// Reference ID    : 0A7CD814 (bn-ntp-01.sbb.ch)
			// Stratum         : 2
			// Ref time (UTC)  : Thu May 31 13:41:40 2018
			// System time     : 0.000037743 seconds fast of NTP time
			// Last offset     : +0.000061081 seconds <--- SECONDS
			// RMS offset      : 0.000333012 seconds
			// Frequency       : 6.629 ppm fast
			// Residual freq   : +0.004 ppm
			// Skew            : 0.140 ppm
			// Root delay      : 0.002649408 seconds
			// Root dispersion : 0.000559144 seconds
			// Update interval : 517.4 seconds
			// Leap status     : Normal
			rgx := regexp.MustCompile("(.*offset\\s+:\\s+)(.*?)\\s+seconds")
			offset := rgx.FindStringSubmatch(line)

			log.Println("Found chrony offset:", offset[2])
			out, err := strconv.ParseFloat(offset[2], 64)
			if err != nil {
				return -1000, fmt.Errorf("couldn't parse chrony offset. Value was %v", offset[2])
			}
			return out, nil
		}
	}
	return -1000, fmt.Errorf("couldn't parse chrony offset. Offset line was not found.")
}

func CheckNtpd() error {
	log.Println("Checking output of 'ntpq -c rv 0 offset'")

	out, err := exec.Command("bash", "-c", "ntpq -c rv 0 offset").Output()
	if err != nil {
		msg := "Could not check ntpd status: " + err.Error()
		log.Println(msg)
		return errors.New(msg)
	}

	offset, err := parseNTPOffsetFromNTPD(string(out))

	if offset < -100 || offset > 100 {
		return errors.New("Time is not correct on the server or ntpd is not running")
	} else {
		return nil
	}
}

func parseNTPOffsetFromNTPD(out string) (float64, error) {
	for _, l := range strings.Split(string(out), "\n") {
		if strings.Contains(l, "offset") {
			// Example output
			// mintc=3, offset=0.400, frequency=-4.546, sys_jitter=1.015,
			// tc=10, mintc=3, offset=-0.648, frequency=3.934, sys_jitter=0.253,
			rgx := regexp.MustCompile("(.*offset=)(.*?),")
			offset := rgx.FindStringSubmatch(l)

			log.Println("Found ntpd offset:", offset[2])
			out, err := strconv.ParseFloat(offset[2], 64)
			if err != nil {
				return -1000, fmt.Errorf("couldn't parse ntp offset. Value was %v", offset[2])
			}
			return out, nil
		}
	}
	return -1000, fmt.Errorf("couldn't parse ntp offset. Offset line was not found.")
}

func getIpsForName(n string) []net.IP {
	ips, err := net.LookupIP(n)
	if err != nil {
		log.Println("failed to lookup ip for name ", n)
		return nil
	}
	return ips
}

func checkHttp(toCall string) error {
	log.Println("Checking access to:", toCall)
	if strings.HasPrefix(toCall, "https") {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
		client := &http.Client{Transport: tr}
		resp, err := client.Get(toCall)
		if err != nil {
			log.Println("error in http check: ", err)
			return err
		} else {
			resp.Body.Close()
			return nil
		}
	} else {
		resp, err := http.Get(toCall)
		if err != nil {
			log.Println("error in http check: ", err)
			return err
		} else {
			resp.Body.Close()
			return nil
		}
	}
}

func getEndpoint(slow bool) string {
	if slow {
		return "slow"
	} else {
		return "fast"
	}
}

// isVgSizeOk returns true if vgs output in stdOut indicates that the volume
// group free space is equal or above the percentage treshold okSize, which is
// expected to be in the range [0, 100].
func isVgSizeOk(stdOut string, okSize int) bool {
	// Example
	// 5.37 26.84 vg_fast_registry
	// 5.37 26.84 vg_slow
	nums := num.FindAllString(stdOut, 2)

	if len(nums) != 2 {
		log.Println("Unable to parse vgs output:", stdOut)
		return false
	}

	free, err := strconv.ParseFloat(nums[0], 64)
	if err != nil {
		log.Println("Unable to parse first digit of output", stdOut)
		return false
	}
	size, err := strconv.ParseFloat(nums[1], 64)
	if err != nil {
		log.Println("Unable to parse second digit of output", stdOut)
		return false
	}

	// calculate usage
	if 100/size*free < float64(okSize) {
		msg := fmt.Sprintf("VG free size is below treshold. Size: %v, free: %v, treshold: %v %%", size, free, okSize)
		log.Println(msg)
		return false
	}

	return true
}

// isLvsSizeOk returns true if lvs output in stdOut indicates that the logical
// volume percentage full for data and metadata are both below the threshold
// okSize, which is expected to be in the range [0, 100].
func isLvsSizeOk(stdOut string, okSize int) bool {
	// Examples
	// 42.10  8.86   docker-pool
	// 13.63  8.93   lv_fast_registry_pool
	checksOk := 0
	for _, nr := range num.FindAllString(stdOut, -1) {
		i, err := strconv.ParseFloat(nr, 64)
		if err != nil {
			log.Print("Unable to parse int:", nr)
			return false
		}

		if i < float64(okSize) {
			checksOk++
		} else {
			log.Println("LVM pool size exceeded okSize:", i)
		}
	}

	return checksOk == 2
}
<|endoftext|>


<commit_before>package queue

type Queue struct {
	queue []interface{}
	len   int
}

func New() *Queue {
	queue := &Queue{}
	queue.queue = make([]interface{}, 0)
	queue.len = 0

	return queue
}

func (q *Queue) Len() int {
	return q.len
}

func (q *Queue) isEmpty() bool {
	return q.len == 0
}

func (q *Queue) Shift() (el interface{}) {
	el, q.queue = q.queue[0], q.queue[1:]
	q.len--
	return
}

func (q *Queue) Push(el interface{}) {
	q.queue = append(q.queue, el)
	q.len++

	return
}

func (q *Queue) Peek() interface{} {
	return q.queue[0]
}
<commit_msg>Queue: add mutex back<commit_after>package queue

import "sync"

type Queue struct {
	queue []interface{}
	len   int
	lock  *sync.Mutex
}

func New() *Queue {
	queue := &Queue{}
	queue.queue = make([]interface{}, 0)
	queue.len = 0
	queue.lock = new(sync.Mutex)

	return queue
}

func (q *Queue) Len() int {
	q.lock.Lock()
	defer q.lock.Unlock()

	return q.len
}

func (q *Queue) isEmpty() bool {
	q.lock.Lock()
	defer q.lock.Unlock()

	return q.len == 0
}

func (q *Queue) Shift() (el interface{}) {
	q.lock.Lock()
	defer q.lock.Unlock()

	el, q.queue = q.queue[0], q.queue[1:]
	q.len--
	return
}

func (q *Queue) Push(el interface{}) {
	q.lock.Lock()
	defer q.lock.Unlock()

	q.queue = append(q.queue, el)
	q.len++
}

func (q *Queue) Peek() interface{} {
	q.lock.Lock()
	defer q.lock.Unlock()

	return q.queue[0]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"sync"

	"os"

	"github.com/bitly/go-simplejson"
)

const (
	KubernetesAPIServer = "192.168.1.200:8080"
	Port                = ":55123"
	Tag                 = "raft"
)

var (
	hosts    []string
	next     int = 0
	nextLock sync.Mutex
)

func UpdateHosts() error {
	hst, err := getIPsFromKubernetes(Tag)

	hosts = hst

	return err
}

func Update(rw http.ResponseWriter, req *http.Request) {
	err := UpdateHosts()

	if err != nil {
		fmt.Fprintln(rw, err)
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}

	fmt.Fprintln(rw, "Hosts: ", hosts)
}

func Hosts(rw http.ResponseWriter, req *http.Request) {
	fmt.Fprintln(rw, "Hosts: ", hosts)
}

func Forward(rw http.ResponseWriter, req *http.Request) {
	nextLock.Lock()
	host := hosts[next]
	next = (next + 1) % len(hosts)
	nextLock.Unlock()

	url := host + Port + req.URL.Path

	log.Printf("fowarding: %v", url)

	resp, err := http.Get("http://" + url)

	if err != nil {
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}

	rw.WriteHeader(resp.StatusCode)
	rw.Write(body)
}

func main() {

	http.HandleFunc("/update", Update)
	http.HandleFunc("/hosts", Hosts)
	http.HandleFunc("/", Forward)

	if UpdateHosts() != nil {
		fmt.Println("Error on initial update!")
		os.Exit(1)
	}

	http.ListenAndServe(":12345", nil)

}

func getIPsFromKubernetes(tag string) ([]string, error) {
	log.Printf("starting getIPsFromKubernetes(%s)\n", tag)

	resp, err := http.Get("http://" + KubernetesAPIServer + "/api/v1/namespaces/default/endpoints/" + tag)

	if err != nil {
		return nil, err
	}

	log.Println("GET successful")

	defer resp.Body.Close()

	content, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return nil, err
	}

	log.Println("Read body")

	json, err := simplejson.NewJson(content)

	if err != nil {
		return nil, err
	}

	log.Println("Parsing json")

	replicas := make([]string, 0)

	addresses := json.Get("subsets").GetIndex(0).Get("addresses")

	for i := 0; ; i++ {

		ip, err := addresses.GetIndex(i).Get("ip").String()

		if err != nil {
			break
		}

		replicas = append(replicas, ip)
	}

	log.Printf("Done: %v\n", replicas)

	return replicas, nil
}
<commit_msg>Fix firewall imports<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"sync"

	"github.com/bitly/go-simplejson"
)

const (
	KubernetesAPIServer = "192.168.1.200:8080"
	Port                = ":55123"
	Tag                 = "raft"
)

var (
	hosts    []string
	next     int = 0
	nextLock sync.Mutex
)

func UpdateHosts() error {
	hst, err := getIPsFromKubernetes(Tag)

	hosts = hst

	return err
}

func Update(rw http.ResponseWriter, req *http.Request) {
	err := UpdateHosts()

	if err != nil {
		fmt.Fprintln(rw, err)
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}

	fmt.Fprintln(rw, "Hosts: ", hosts)
}

func Hosts(rw http.ResponseWriter, req *http.Request) {
	fmt.Fprintln(rw, "Hosts: ", hosts)
}

func Forward(rw http.ResponseWriter, req *http.Request) {
	nextLock.Lock()
	host := hosts[next]
	next = (next + 1) % len(hosts)
	nextLock.Unlock()

	url := host + Port + req.URL.Path

	log.Printf("fowarding: %v", url)

	resp, err := http.Get("http://" + url)

	if err != nil {
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		rw.WriteHeader(http.StatusInternalServerError)
		return
	}

	rw.WriteHeader(resp.StatusCode)
	rw.Write(body)
}

func main() {

	http.HandleFunc("/update", Update)
	http.HandleFunc("/hosts", Hosts)
	http.HandleFunc("/", Forward)

	if UpdateHosts() != nil {
		fmt.Println("Error on initial update!")
		os.Exit(1)
	}

	http.ListenAndServe(":12345", nil)

}

func getIPsFromKubernetes(tag string) ([]string, error) {
	log.Printf("starting getIPsFromKubernetes(%s)\n", tag)

	resp, err := http.Get("http://" + KubernetesAPIServer + "/api/v1/namespaces/default/endpoints/" + tag)

	if err != nil {
		return nil, err
	}

	log.Println("GET successful")

	defer resp.Body.Close()

	content, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return nil, err
	}

	log.Println("Read body")

	json, err := simplejson.NewJson(content)

	if err != nil {
		return nil, err
	}

	log.Println("Parsing json")

	replicas := make([]string, 0)

	addresses := json.Get("subsets").GetIndex(0).Get("addresses")

	for i := 0; ; i++ {

		ip, err := addresses.GetIndex(i).Get("ip").String()

		if err != nil {
			break
		}

		replicas = append(replicas, ip)
	}

	log.Printf("Done: %v\n", replicas)

	return replicas, nil
}
<|endoftext|>


<commit_before>package udp_tracker

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"io"
	"net"
	"sync"
	"syscall"
	"testing"

	"bitbucket.org/anacrolix/go.torrent/tracker"
)

// Ensure net.IPs are stored big-endian, to match the way they're read from
// the wire.
func TestNetIPv4Bytes(t *testing.T) {
	ip := net.IP([]byte{127, 0, 0, 1})
	if ip.String() != "127.0.0.1" {
		t.FailNow()
	}
	if string(ip) != "\x7f\x00\x00\x01" {
		t.Fatal([]byte(ip))
	}
}

func TestMarshalAnnounceResponse(t *testing.T) {
	w := bytes.NewBuffer(nil)
	if err := binary.Write(w, binary.BigEndian, []Peer{{[4]byte{127, 0, 0, 1}, 2}, {[4]byte{255, 0, 0, 3}, 4}}); err != nil {
		t.Fatalf("error writing udp announce response addrs: %s", err)
	}
	if w.String() != "\x7f\x00\x00\x01\x00\x02\xff\x00\x00\x03\x00\x04" {
		t.FailNow()
	}
	if binary.Size(AnnounceResponseHeader{}) != 12 {
		t.FailNow()
	}
}

// Failure to write an entire packet to UDP is expected to given an error.
func TestLongWriteUDP(t *testing.T) {
	l, err := net.ListenUDP("udp", nil)
	defer l.Close()
	if err != nil {
		t.Fatal(err)
	}
	c, err := net.DialUDP("udp", nil, l.LocalAddr().(*net.UDPAddr))
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()
	for msgLen := 1; ; msgLen *= 2 {
		n, err := c.Write(make([]byte, msgLen))
		if err != nil {
			err := err.(*net.OpError).Err
			if err != syscall.EMSGSIZE {
				t.Fatalf("write error isn't EMSGSIZE: %s", err)
			}
			return
		}
		if n < msgLen {
			t.FailNow()
		}
	}
}

func TestShortBinaryRead(t *testing.T) {
	var data ResponseHeader
	err := binary.Read(bytes.NewBufferString("\x00\x00\x00\x01"), binary.BigEndian, &data)
	if data.Action != 0 {
		t.Log("optimistic binary read now works?!")
	}
	switch err {
	case io.ErrUnexpectedEOF:
	default:
		// TODO
	}
}

func TestConvertInt16ToInt(t *testing.T) {
	i := 50000
	if int(uint16(int16(i))) != 50000 {
		t.FailNow()
	}
}

func TestUDPTracker(t *testing.T) {
	tr, err := tracker.New("udp://tracker.openbittorrent.com:80/announce")
	if err != nil {
		t.Fatal(err)
	}
	if err := tr.Connect(); err != nil {
		t.Fatal(err)
	}
	req := tracker.AnnounceRequest{
		NumWant: -1,
		Event:   tracker.Started,
	}
	rand.Read(req.PeerId[:])
	copy(req.InfoHash[:], []uint8{0xa3, 0x56, 0x41, 0x43, 0x74, 0x23, 0xe6, 0x26, 0xd9, 0x38, 0x25, 0x4a, 0x6b, 0x80, 0x49, 0x10, 0xa6, 0x67, 0xa, 0xc1})
	_, err = tr.Announce(&req)
	if err != nil {
		t.Fatal(err)
	}
}

// TODO: Create a fake UDP tracker to make these requests to.
func TestAnnounceRandomInfoHash(t *testing.T) {
	wg := sync.WaitGroup{}
	for _, url := range []string{
		"udp://tracker.openbittorrent.com:80/announce",
		"udp://tracker.publicbt.com:80",
		"udp://tracker.istole.it:6969",
		"udp://tracker.ccc.de:80",
		"udp://tracker.open.demonii.com:1337",
	} {
		go func(url string) {
			defer wg.Done()
			tr, err := tracker.New(url)
			if err != nil {
				t.Fatal(err)
			}
			if err := tr.Connect(); err != nil {
				t.Log(err)
				return
			}
			req := tracker.AnnounceRequest{
				Event: tracker.Stopped,
			}
			rand.Read(req.PeerId[:])
			rand.Read(req.InfoHash[:])
			resp, err := tr.Announce(&req)
			if err != nil {
				t.Logf("error announcing to %s: %s", url, err)
				return
			}
			if resp.Leechers != 0 || resp.Seeders != 0 || len(resp.Peers) != 0 {
				t.Fatal(resp)
			}
		}(url)
		wg.Add(1)
	}
	wg.Wait()
}
<commit_msg>Skip on errors testing UDP tracker, need to implement a fake server<commit_after>package udp_tracker

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"io"
	"net"
	"sync"
	"syscall"
	"testing"

	"bitbucket.org/anacrolix/go.torrent/tracker"
)

// Ensure net.IPs are stored big-endian, to match the way they're read from
// the wire.
func TestNetIPv4Bytes(t *testing.T) {
	ip := net.IP([]byte{127, 0, 0, 1})
	if ip.String() != "127.0.0.1" {
		t.FailNow()
	}
	if string(ip) != "\x7f\x00\x00\x01" {
		t.Fatal([]byte(ip))
	}
}

func TestMarshalAnnounceResponse(t *testing.T) {
	w := bytes.NewBuffer(nil)
	if err := binary.Write(w, binary.BigEndian, []Peer{{[4]byte{127, 0, 0, 1}, 2}, {[4]byte{255, 0, 0, 3}, 4}}); err != nil {
		t.Fatalf("error writing udp announce response addrs: %s", err)
	}
	if w.String() != "\x7f\x00\x00\x01\x00\x02\xff\x00\x00\x03\x00\x04" {
		t.FailNow()
	}
	if binary.Size(AnnounceResponseHeader{}) != 12 {
		t.FailNow()
	}
}

// Failure to write an entire packet to UDP is expected to given an error.
func TestLongWriteUDP(t *testing.T) {
	l, err := net.ListenUDP("udp", nil)
	defer l.Close()
	if err != nil {
		t.Fatal(err)
	}
	c, err := net.DialUDP("udp", nil, l.LocalAddr().(*net.UDPAddr))
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()
	for msgLen := 1; ; msgLen *= 2 {
		n, err := c.Write(make([]byte, msgLen))
		if err != nil {
			err := err.(*net.OpError).Err
			if err != syscall.EMSGSIZE {
				t.Fatalf("write error isn't EMSGSIZE: %s", err)
			}
			return
		}
		if n < msgLen {
			t.FailNow()
		}
	}
}

func TestShortBinaryRead(t *testing.T) {
	var data ResponseHeader
	err := binary.Read(bytes.NewBufferString("\x00\x00\x00\x01"), binary.BigEndian, &data)
	if data.Action != 0 {
		t.Log("optimistic binary read now works?!")
	}
	switch err {
	case io.ErrUnexpectedEOF:
	default:
		// TODO
	}
}

func TestConvertInt16ToInt(t *testing.T) {
	i := 50000
	if int(uint16(int16(i))) != 50000 {
		t.FailNow()
	}
}

func TestUDPTracker(t *testing.T) {
	tr, err := tracker.New("udp://tracker.openbittorrent.com:80/announce")
	if err != nil {
		t.Skip(err)
	}
	if err := tr.Connect(); err != nil {
		t.Skip(err)
	}
	req := tracker.AnnounceRequest{
		NumWant: -1,
		Event:   tracker.Started,
	}
	rand.Read(req.PeerId[:])
	copy(req.InfoHash[:], []uint8{0xa3, 0x56, 0x41, 0x43, 0x74, 0x23, 0xe6, 0x26, 0xd9, 0x38, 0x25, 0x4a, 0x6b, 0x80, 0x49, 0x10, 0xa6, 0x67, 0xa, 0xc1})
	_, err = tr.Announce(&req)
	if err != nil {
		t.Skip(err)
	}
}

// TODO: Create a fake UDP tracker to make these requests to.
func TestAnnounceRandomInfoHash(t *testing.T) {
	wg := sync.WaitGroup{}
	for _, url := range []string{
		"udp://tracker.openbittorrent.com:80/announce",
		"udp://tracker.publicbt.com:80",
		"udp://tracker.istole.it:6969",
		"udp://tracker.ccc.de:80",
		"udp://tracker.open.demonii.com:1337",
	} {
		go func(url string) {
			defer wg.Done()
			tr, err := tracker.New(url)
			if err != nil {
				t.Fatal(err)
			}
			if err := tr.Connect(); err != nil {
				t.Log(err)
				return
			}
			req := tracker.AnnounceRequest{
				Event: tracker.Stopped,
			}
			rand.Read(req.PeerId[:])
			rand.Read(req.InfoHash[:])
			resp, err := tr.Announce(&req)
			if err != nil {
				t.Logf("error announcing to %s: %s", url, err)
				return
			}
			if resp.Leechers != 0 || resp.Seeders != 0 || len(resp.Peers) != 0 {
				t.Fatal(resp)
			}
		}(url)
		wg.Add(1)
	}
	wg.Wait()
}
<|endoftext|>


<commit_before>package factordb

import (
	"testing"

	"github.com/sourcekris/goRsaTool/keys"
	fmp "github.com/sourcekris/goflint"
)

func TestFactorDB(t *testing.T) {
	n, _ := new(fmp.Fmpz).SetString("833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019", 10)
	d, _ := new(fmp.Fmpz).SetString("521250646663056391768764366517618655312275374668692430321064634566533568373969990465313092928455546989832961905578375473", 10)

	fmpPubKey := &keys.FMPPublicKey{
		N: n,
		E: fmp.NewFmpz(65537),
	}

	targetRSA, _ := keys.NewRSA(keys.PrivateFromPublic(fmpPubKey), nil, nil, "", false)
	if err := Attack(targetRSA); err != nil {
		t.Fatalf("got unexpected error: %v", err)
	}

	if targetRSA.Key.D.Cmp(d) != 0 {
		t.Errorf("got %v wanted %v for d\n", targetRSA.Key.D, d)
	}
}
<commit_msg>Add test for solveforP()<commit_after>package factordb

import (
	"testing"

	"github.com/sourcekris/goRsaTool/keys"
	"github.com/sourcekris/goRsaTool/ln"
	fmp "github.com/sourcekris/goflint"
)

func TestFactorDB(t *testing.T) {
	n, _ := new(fmp.Fmpz).SetString("833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019", 10)
	d, _ := new(fmp.Fmpz).SetString("521250646663056391768764366517618655312275374668692430321064634566533568373969990465313092928455546989832961905578375473", 10)

	fmpPubKey := &keys.FMPPublicKey{
		N: n,
		E: fmp.NewFmpz(65537),
	}

	targetRSA, _ := keys.NewRSA(keys.PrivateFromPublic(fmpPubKey), nil, nil, "", false)
	if err := Attack(targetRSA); err != nil {
		t.Fatalf("got unexpected error: %v", err)
	}

	if targetRSA.Key.D.Cmp(d) != 0 {
		t.Errorf("got %v wanted %v for d\n", targetRSA.Key.D, d)
	}
}

func TestSolveForP(t *testing.T) {
	tt := []struct {
		name    string
		eq      string
		want    *fmp.Fmpz
		wantErr bool
	}{
		{
			name: "expected equation format",
			eq:   "2^10-1",
			want: fmp.NewFmpz(1023),
		},
		{
			name:    "partial equation format",
			eq:      "2^10",
			want:    fmp.NewFmpz(-1),
			wantErr: true,
		},
		{
			name:    "unexpected equation format",
			eq:      "2+4-1",
			want:    fmp.NewFmpz(-1),
			wantErr: true,
		},
		{
			name:    "empty equation",
			eq:      "",
			want:    fmp.NewFmpz(-1),
			wantErr: true,
		},
	}

	for _, tc := range tt {
		got := solveforP(tc.eq)
		if tc.want.Cmp(got) != 0 && !tc.wantErr {
			t.Errorf("solveforP: %s failed - got %v want %v", tc.name, got, tc.want)
		}

		if got.Cmp(ln.BigZero) == 0 && !tc.wantErr {
			t.Errorf("solveforP: %s unexpected error", tc.name)
		}

		if got.Cmp(ln.BigZero) != 0 && tc.wantErr {
			t.Errorf("solveforP: %s unexpected result when expected error: %v", tc.name, got)
		}
	}
}
<|endoftext|>


<commit_before>package application

import (
	"cf"
	"cf/api"
	"cf/configuration"
	"cf/requirements"
	"cf/terminal"
	"errors"
	"fmt"
	"github.com/cloudfoundry/loggregatorlib/logmessage"
	"github.com/codegangsta/cli"
	"os"
	"strconv"
	"strings"
	"time"
)

const (
	DefaultStagingTimeout = 20 * time.Minute
	DefaultStartupTimeout = 5 * time.Minute
	DefaultPingerThrottle = 5 * time.Second
)

const LogMessageTypeStaging = "STG"

type Start struct {
	ui               terminal.UI
	config           *configuration.Configuration
	appDisplayer     ApplicationDisplayer
	appReq           requirements.ApplicationRequirement
	appRepo          api.ApplicationRepository
	appInstancesRepo api.AppInstancesRepository
	logRepo          api.LogsRepository

	StartupTimeout time.Duration
	StagingTimeout time.Duration
	PingerThrottle time.Duration
}

type ApplicationStarter interface {
	ApplicationStart(app cf.Application) (updatedApp cf.Application, err error)
}

func NewStart(ui terminal.UI, config *configuration.Configuration, appDisplayer ApplicationDisplayer, appRepo api.ApplicationRepository, appInstancesRepo api.AppInstancesRepository, logRepo api.LogsRepository) (cmd *Start) {
	cmd = new(Start)
	cmd.ui = ui
	cmd.config = config
	cmd.appDisplayer = appDisplayer
	cmd.appRepo = appRepo
	cmd.appInstancesRepo = appInstancesRepo
	cmd.logRepo = logRepo

	cmd.PingerThrottle = DefaultPingerThrottle

	if os.Getenv("CF_STAGING_TIMEOUT") != "" {
		duration, err := strconv.ParseInt(os.Getenv("CF_STAGING_TIMEOUT"), 10, 64)
		if err != nil {
			cmd.ui.Failed("invalid value for env var CF_STAGING_TIMEOUT\n%s", err)
		}
		cmd.StagingTimeout = time.Duration(duration) * time.Minute
	} else {
		cmd.StagingTimeout = DefaultStagingTimeout
	}

	if os.Getenv("CF_STARTUP_TIMEOUT") != "" {
		duration, err := strconv.ParseInt(os.Getenv("CF_STARTUP_TIMEOUT"), 10, 64)
		if err != nil {
			cmd.ui.Failed("invalid value for env var CF_STARTUP_TIMEOUT\n%s", err)
		}
		cmd.StartupTimeout = time.Duration(duration) * time.Minute
	} else {
		cmd.StartupTimeout = DefaultStartupTimeout
	}

	return
}

func (cmd *Start) GetRequirements(reqFactory requirements.Factory, c *cli.Context) (reqs []requirements.Requirement, err error) {
	if len(c.Args()) == 0 {
		err = errors.New("Incorrect Usage")
		cmd.ui.FailWithUsage(c, "start")
		return
	}

	cmd.appReq = reqFactory.NewApplicationRequirement(c.Args()[0])

	reqs = []requirements.Requirement{cmd.appReq}
	return
}

func (cmd *Start) Run(c *cli.Context) {
	cmd.ApplicationStart(cmd.appReq.GetApplication())
}

func (cmd *Start) ApplicationStart(app cf.Application) (updatedApp cf.Application, err error) {
	if app.State == "started" {
		cmd.ui.Say(terminal.WarningColor("App " + app.Name + " is already started"))
		return
	}

	cmd.ui.Say("Starting app %s in org %s / space %s as %s...",
		terminal.EntityNameColor(app.Name),
		terminal.EntityNameColor(cmd.config.OrganizationFields.Name),
		terminal.EntityNameColor(cmd.config.SpaceFields.Name),
		terminal.EntityNameColor(cmd.config.Username()),
	)

	params := cf.NewEmptyAppParams()
	params.Set("state", "STARTED")

	updatedApp, apiResponse := cmd.appRepo.Update(app.Guid, params)

	if apiResponse.IsNotSuccessful() {
		cmd.ui.Failed(apiResponse.Message)
		return
	}

	cmd.ui.Ok()

	stopLoggingChan := make(chan bool, 1)
	defer close(stopLoggingChan)
	go cmd.tailStagingLogs(app, stopLoggingChan)

	cmd.waitForInstancesToStage(updatedApp)
	stopLoggingChan <- true

	cmd.ui.Say("")

	cmd.waitForOneRunningInstance(app.Guid)
	cmd.ui.Say(terminal.HeaderColor("\nApp started\n"))

	cmd.appDisplayer.ShowApp(app)
	return
}

func (cmd Start) tailStagingLogs(app cf.Application, stopChan chan bool) {
	logChan := make(chan *logmessage.Message, 1000)
	go func() {
		defer close(logChan)

		err := cmd.logRepo.TailLogsFor(app.Guid, func() {}, logChan, stopChan, 1)
		if err != nil {
			cmd.ui.Warn("Warning: error tailing logs")
			cmd.ui.Say("%s", err)
		}
	}()

	cmd.displayLogMessages(logChan)
}

func (cmd Start) displayLogMessages(logChan chan *logmessage.Message) {
	for msg := range logChan {
		if msg.GetShortSourceTypeName() != LogMessageTypeStaging {
			continue
		}
		cmd.ui.Say(simpleLogMessageOutput(msg))
	}
}

func (cmd Start) waitForInstancesToStage(app cf.Application) {
	stagingStartTime := time.Now()
	_, apiResponse := cmd.appInstancesRepo.GetInstances(app.Guid)

	for apiResponse.IsNotSuccessful() && time.Since(stagingStartTime) < cmd.StagingTimeout {
		if apiResponse.ErrorCode != cf.APP_NOT_STAGED {
			cmd.ui.Say("")
			cmd.ui.Failed(apiResponse.Message)
			return
		}
		cmd.ui.Wait(cmd.PingerThrottle)
		_, apiResponse = cmd.appInstancesRepo.GetInstances(app.Guid)
	}
	return
}

func (cmd Start) waitForOneRunningInstance(appGuid string) {
	var runningCount, startingCount, flappingCount, downCount int
	startupStartTime := time.Now()

	for runningCount == 0 {
		cmd.ui.Wait(cmd.PingerThrottle)
		instances, apiResponse := cmd.appInstancesRepo.GetInstances(appGuid)
		if apiResponse.IsNotSuccessful() {
			continue
		}

		totalCount := len(instances)
		runningCount, startingCount, flappingCount, downCount = 0, 0, 0, 0

		for _, inst := range instances {
			switch inst.State {
			case cf.InstanceRunning:
				runningCount++
			case cf.InstanceStarting:
				startingCount++
			case cf.InstanceFlapping:
				flappingCount++
			case cf.InstanceDown:
				downCount++
			}
		}

		cmd.ui.Say(instancesDetails(startingCount, downCount, runningCount, flappingCount, totalCount))

		if flappingCount > 0 {
			cmd.ui.Failed("Start unsuccessful")
			return
		}

		if time.Since(startupStartTime) > cmd.StartupTimeout {
			cmd.ui.Failed("Start app timeout")
			return
		}
	}
}

func instancesDetails(startingCount, downCount, runningCount, flappingCount, totalCount int) string {
	details := []string{fmt.Sprintf("%d of %d instances running", runningCount, totalCount)}

	if startingCount > 0 {
		details = append(details, fmt.Sprintf("%d starting", startingCount))
	}

	if downCount > 0 {
		details = append(details, fmt.Sprintf("%d down", downCount))
	}

	if flappingCount > 0 {
		details = append(details, fmt.Sprintf("%d failing", flappingCount))
	}

	return strings.Join(details, ", ")
}
<commit_msg>Connect to loggregator before starting an app<commit_after>package application

import (
	"cf"
	"cf/api"
	"cf/configuration"
	"cf/requirements"
	"cf/terminal"
	"errors"
	"fmt"
	"github.com/cloudfoundry/loggregatorlib/logmessage"
	"github.com/codegangsta/cli"
	"os"
	"strconv"
	"strings"
	"time"
)

const (
	DefaultStagingTimeout = 20 * time.Minute
	DefaultStartupTimeout = 5 * time.Minute
	DefaultPingerThrottle = 5 * time.Second
)

const LogMessageTypeStaging = "STG"

type Start struct {
	ui               terminal.UI
	config           *configuration.Configuration
	appDisplayer     ApplicationDisplayer
	appReq           requirements.ApplicationRequirement
	appRepo          api.ApplicationRepository
	appInstancesRepo api.AppInstancesRepository
	logRepo          api.LogsRepository

	StartupTimeout time.Duration
	StagingTimeout time.Duration
	PingerThrottle time.Duration
}

type ApplicationStarter interface {
	ApplicationStart(app cf.Application) (updatedApp cf.Application, err error)
}

func NewStart(ui terminal.UI, config *configuration.Configuration, appDisplayer ApplicationDisplayer, appRepo api.ApplicationRepository, appInstancesRepo api.AppInstancesRepository, logRepo api.LogsRepository) (cmd *Start) {
	cmd = new(Start)
	cmd.ui = ui
	cmd.config = config
	cmd.appDisplayer = appDisplayer
	cmd.appRepo = appRepo
	cmd.appInstancesRepo = appInstancesRepo
	cmd.logRepo = logRepo

	cmd.PingerThrottle = DefaultPingerThrottle

	if os.Getenv("CF_STAGING_TIMEOUT") != "" {
		duration, err := strconv.ParseInt(os.Getenv("CF_STAGING_TIMEOUT"), 10, 64)
		if err != nil {
			cmd.ui.Failed("invalid value for env var CF_STAGING_TIMEOUT\n%s", err)
		}
		cmd.StagingTimeout = time.Duration(duration) * time.Minute
	} else {
		cmd.StagingTimeout = DefaultStagingTimeout
	}

	if os.Getenv("CF_STARTUP_TIMEOUT") != "" {
		duration, err := strconv.ParseInt(os.Getenv("CF_STARTUP_TIMEOUT"), 10, 64)
		if err != nil {
			cmd.ui.Failed("invalid value for env var CF_STARTUP_TIMEOUT\n%s", err)
		}
		cmd.StartupTimeout = time.Duration(duration) * time.Minute
	} else {
		cmd.StartupTimeout = DefaultStartupTimeout
	}

	return
}

func (cmd *Start) GetRequirements(reqFactory requirements.Factory, c *cli.Context) (reqs []requirements.Requirement, err error) {
	if len(c.Args()) == 0 {
		err = errors.New("Incorrect Usage")
		cmd.ui.FailWithUsage(c, "start")
		return
	}

	cmd.appReq = reqFactory.NewApplicationRequirement(c.Args()[0])

	reqs = []requirements.Requirement{cmd.appReq}
	return
}

func (cmd *Start) Run(c *cli.Context) {
	cmd.ApplicationStart(cmd.appReq.GetApplication())
}

func (cmd *Start) ApplicationStart(app cf.Application) (updatedApp cf.Application, err error) {
	if app.State == "started" {
		cmd.ui.Say(terminal.WarningColor("App " + app.Name + " is already started"))
		return
	}

	stopLoggingChan := make(chan bool, 1)
	defer close(stopLoggingChan)
	loggingStartedChan := make(chan bool)
	defer close(loggingStartedChan)

	go cmd.tailStagingLogs(app, loggingStartedChan, stopLoggingChan)

	<-loggingStartedChan

	cmd.ui.Say("Starting app %s in org %s / space %s as %s...",
		terminal.EntityNameColor(app.Name),
		terminal.EntityNameColor(cmd.config.OrganizationFields.Name),
		terminal.EntityNameColor(cmd.config.SpaceFields.Name),
		terminal.EntityNameColor(cmd.config.Username()),
	)

	params := cf.NewEmptyAppParams()
	params.Set("state", "STARTED")

	updatedApp, apiResponse := cmd.appRepo.Update(app.Guid, params)

	if apiResponse.IsNotSuccessful() {
		cmd.ui.Failed(apiResponse.Message)
		return
	}

	cmd.ui.Ok()

	cmd.waitForInstancesToStage(updatedApp)
	stopLoggingChan <- true

	cmd.ui.Say("")

	cmd.waitForOneRunningInstance(app.Guid)
	cmd.ui.Say(terminal.HeaderColor("\nApp started\n"))

	cmd.appDisplayer.ShowApp(app)
	return
}

func (cmd Start) tailStagingLogs(app cf.Application, startChan chan bool, stopChan chan bool) {
	logChan := make(chan *logmessage.Message, 1000)
	go func() {
		defer close(logChan)

		onConnect := func() {
			startChan <- true
		}

		err := cmd.logRepo.TailLogsFor(app.Guid, onConnect, logChan, stopChan, 1)
		if err != nil {
			cmd.ui.Warn("Warning: error tailing logs")
			cmd.ui.Say("%s", err)
			startChan <- true
		}
	}()

	cmd.displayLogMessages(logChan)
}

func (cmd Start) displayLogMessages(logChan chan *logmessage.Message) {
	for msg := range logChan {
		if msg.GetShortSourceTypeName() != LogMessageTypeStaging {
			continue
		}
		cmd.ui.Say(simpleLogMessageOutput(msg))
	}
}

func (cmd Start) waitForInstancesToStage(app cf.Application) {
	stagingStartTime := time.Now()
	_, apiResponse := cmd.appInstancesRepo.GetInstances(app.Guid)

	for apiResponse.IsNotSuccessful() && time.Since(stagingStartTime) < cmd.StagingTimeout {
		if apiResponse.ErrorCode != cf.APP_NOT_STAGED {
			cmd.ui.Say("")
			cmd.ui.Failed(apiResponse.Message)
			return
		}
		cmd.ui.Wait(cmd.PingerThrottle)
		_, apiResponse = cmd.appInstancesRepo.GetInstances(app.Guid)
	}
	return
}

func (cmd Start) waitForOneRunningInstance(appGuid string) {
	var runningCount, startingCount, flappingCount, downCount int
	startupStartTime := time.Now()

	for runningCount == 0 {
		cmd.ui.Wait(cmd.PingerThrottle)
		instances, apiResponse := cmd.appInstancesRepo.GetInstances(appGuid)
		if apiResponse.IsNotSuccessful() {
			continue
		}

		totalCount := len(instances)
		runningCount, startingCount, flappingCount, downCount = 0, 0, 0, 0

		for _, inst := range instances {
			switch inst.State {
			case cf.InstanceRunning:
				runningCount++
			case cf.InstanceStarting:
				startingCount++
			case cf.InstanceFlapping:
				flappingCount++
			case cf.InstanceDown:
				downCount++
			}
		}

		cmd.ui.Say(instancesDetails(startingCount, downCount, runningCount, flappingCount, totalCount))

		if flappingCount > 0 {
			cmd.ui.Failed("Start unsuccessful")
			return
		}

		if time.Since(startupStartTime) > cmd.StartupTimeout {
			cmd.ui.Failed("Start app timeout")
			return
		}
	}
}

func instancesDetails(startingCount, downCount, runningCount, flappingCount, totalCount int) string {
	details := []string{fmt.Sprintf("%d of %d instances running", runningCount, totalCount)}

	if startingCount > 0 {
		details = append(details, fmt.Sprintf("%d starting", startingCount))
	}

	if downCount > 0 {
		details = append(details, fmt.Sprintf("%d down", downCount))
	}

	if flappingCount > 0 {
		details = append(details, fmt.Sprintf("%d failing", flappingCount))
	}

	return strings.Join(details, ", ")
}
<|endoftext|>


<commit_before><commit_msg>Permissions were completely wrong<commit_after><|endoftext|>


<commit_before>package filesys

import (
	"context"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/seaweedfs/fuse"
	"github.com/seaweedfs/fuse/fs"
)

func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirectory fs.Node) error {

	newDir := newDirectory.(*Dir)

	newPath := util.NewFullPath(newDir.FullPath(), req.NewName)
	oldPath := util.NewFullPath(dir.FullPath(), req.OldName)

	glog.V(4).Infof("dir Rename %s => %s", oldPath, newPath)

	err := dir.wfs.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		request := &filer_pb.AtomicRenameEntryRequest{
			OldDirectory: dir.FullPath(),
			OldName:      req.OldName,
			NewDirectory: newDir.FullPath(),
			NewName:      req.NewName,
		}

		_, err := client.AtomicRenameEntry(context.Background(), request)
		if err != nil {
			glog.V(0).Infof("dir Rename %s => %s : %v", oldPath, newPath, err)
			return fuse.EIO
		}

		return nil

	})

	if err == nil {

		// fmt.Printf("rename path: %v => %v\n", oldPath, newPath)
		dir.wfs.fsNodeCache.Move(oldPath, newPath)
		delete(dir.wfs.handles, oldPath.AsInode())

	}

	return err
}
<commit_msg>FUSE: faster rename implementation<commit_after>package filesys

import (
	"context"

	"github.com/seaweedfs/fuse"
	"github.com/seaweedfs/fuse/fs"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func (dir *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDirectory fs.Node) error {

	newDir := newDirectory.(*Dir)

	newPath := util.NewFullPath(newDir.FullPath(), req.NewName)
	oldPath := util.NewFullPath(dir.FullPath(), req.OldName)

	glog.V(4).Infof("dir Rename %s => %s", oldPath, newPath)

	// find local old entry
	oldEntry, err := dir.wfs.metaCache.FindEntry(context.Background(), oldPath)
	if err != nil {
		glog.V(0).Infof("dir Rename can not find %s => %s : %v", oldPath, err)
		return fuse.ENOENT
	}

	// update remote filer
	err = dir.wfs.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error {

		request := &filer_pb.AtomicRenameEntryRequest{
			OldDirectory: dir.FullPath(),
			OldName:      req.OldName,
			NewDirectory: newDir.FullPath(),
			NewName:      req.NewName,
		}

		_, err := client.AtomicRenameEntry(context.Background(), request)
		if err != nil {
			return fuse.EIO
		}

		return nil

	})
	if err != nil {
		glog.V(0).Infof("dir Rename %s => %s : %v", oldPath, newPath, err)
		return fuse.EIO
	}

	// TODO: replicate renaming logic on filer
	if err := dir.wfs.metaCache.DeleteEntry(context.Background(), oldPath); err != nil {
		glog.V(0).Infof("dir Rename delete local %s => %s : %v", oldPath, newPath, err)
		return fuse.EIO
	}
	oldEntry.FullPath = newPath
	if err := dir.wfs.metaCache.InsertEntry(context.Background(), oldEntry); err != nil {
		glog.V(0).Infof("dir Rename insert local %s => %s : %v", oldPath, newPath, err)
		return fuse.EIO
	}

	// fmt.Printf("rename path: %v => %v\n", oldPath, newPath)
	dir.wfs.fsNodeCache.Move(oldPath, newPath)
	delete(dir.wfs.handles, oldPath.AsInode())

	return err
}
<|endoftext|>


<commit_before>package topology

import (
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/util"
	"strconv"
	"sync"

	"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
	"github.com/chrislusf/seaweedfs/weed/storage/erasure_coding"
	"github.com/chrislusf/seaweedfs/weed/storage/needle"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/storage"
)

type DataNode struct {
	NodeImpl
	volumes      map[needle.VolumeId]storage.VolumeInfo
	Ip           string
	Port         int
	PublicUrl    string
	LastSeen     int64 // unix time in seconds
	ecShards     map[needle.VolumeId]*erasure_coding.EcVolumeInfo
	ecShardsLock sync.RWMutex
}

func NewDataNode(id string) *DataNode {
	s := &DataNode{}
	s.id = NodeId(id)
	s.nodeType = "DataNode"
	s.volumes = make(map[needle.VolumeId]storage.VolumeInfo)
	s.ecShards = make(map[needle.VolumeId]*erasure_coding.EcVolumeInfo)
	s.NodeImpl.value = s
	return s
}

func (dn *DataNode) String() string {
	dn.RLock()
	defer dn.RUnlock()
	return fmt.Sprintf("Node:%s, volumes:%v, Ip:%s, Port:%d, PublicUrl:%s", dn.NodeImpl.String(), dn.volumes, dn.Ip, dn.Port, dn.PublicUrl)
}

func (dn *DataNode) AddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChangedRO bool) {
	dn.Lock()
	defer dn.Unlock()
	return dn.doAddOrUpdateVolume(v)
}

func (dn *DataNode) doAddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChangedRO bool) {
	if oldV, ok := dn.volumes[v.Id]; !ok {
		dn.volumes[v.Id] = v
		dn.UpAdjustVolumeCountDelta(1)
		if v.IsRemote() {
			dn.UpAdjustRemoteVolumeCountDelta(1)
		}
		if !v.ReadOnly {
			dn.UpAdjustActiveVolumeCountDelta(1)
		}
		dn.UpAdjustMaxVolumeId(v.Id)
		isNew = true
	} else {
		if oldV.IsRemote() != v.IsRemote() {
			if v.IsRemote() {
				dn.UpAdjustRemoteVolumeCountDelta(1)
			}
			if oldV.IsRemote() {
				dn.UpAdjustRemoteVolumeCountDelta(-1)
			}
		}
		isChangedRO = dn.volumes[v.Id].ReadOnly != v.ReadOnly
		dn.volumes[v.Id] = v
	}
	return
}

func (dn *DataNode) UpdateVolumes(actualVolumes []storage.VolumeInfo) (newVolumes, deletedVolumes, changeRO []storage.VolumeInfo) {

	actualVolumeMap := make(map[needle.VolumeId]storage.VolumeInfo)
	for _, v := range actualVolumes {
		actualVolumeMap[v.Id] = v
	}

	dn.Lock()
	defer dn.Unlock()

	for vid, v := range dn.volumes {
		if _, ok := actualVolumeMap[vid]; !ok {
			glog.V(0).Infoln("Deleting volume id:", vid)
			delete(dn.volumes, vid)
			deletedVolumes = append(deletedVolumes, v)
			dn.UpAdjustVolumeCountDelta(-1)
			if v.IsRemote() {
				dn.UpAdjustRemoteVolumeCountDelta(-1)
			}
			if !v.ReadOnly {
				dn.UpAdjustActiveVolumeCountDelta(-1)
			}
		}
	}
	for _, v := range actualVolumes {
		isNew, isChangedRO := dn.doAddOrUpdateVolume(v)
		if isNew {
			newVolumes = append(newVolumes, v)
		}
		if isChangedRO {
			changeRO = append(changeRO, v)
		}
	}
	return
}

func (dn *DataNode) DeltaUpdateVolumes(newVolumes, deletedVolumes []storage.VolumeInfo) {
	dn.Lock()
	defer dn.Unlock()

	for _, v := range deletedVolumes {
		delete(dn.volumes, v.Id)
		dn.UpAdjustVolumeCountDelta(-1)
		if v.IsRemote() {
			dn.UpAdjustRemoteVolumeCountDelta(-1)
		}
		if !v.ReadOnly {
			dn.UpAdjustActiveVolumeCountDelta(-1)
		}
	}
	for _, v := range newVolumes {
		dn.doAddOrUpdateVolume(v)
	}
	return
}

func (dn *DataNode) GetVolumes() (ret []storage.VolumeInfo) {
	dn.RLock()
	for _, v := range dn.volumes {
		ret = append(ret, v)
	}
	dn.RUnlock()
	return ret
}

func (dn *DataNode) GetVolumesById(id needle.VolumeId) (storage.VolumeInfo, error) {
	dn.RLock()
	defer dn.RUnlock()
	vInfo, ok := dn.volumes[id]
	if ok {
		return vInfo, nil
	} else {
		return storage.VolumeInfo{}, fmt.Errorf("volumeInfo not found")
	}
}

func (dn *DataNode) GetDataCenter() *DataCenter {
	return dn.Parent().Parent().(*NodeImpl).value.(*DataCenter)
}

func (dn *DataNode) GetRack() *Rack {
	return dn.Parent().(*NodeImpl).value.(*Rack)
}

func (dn *DataNode) GetTopology() *Topology {
	p := dn.Parent()
	for p.Parent() != nil {
		p = p.Parent()
	}
	t := p.(*Topology)
	return t
}

func (dn *DataNode) MatchLocation(ip string, port int) bool {
	return dn.Ip == ip && dn.Port == port
}

func (dn *DataNode) Url() string {
	return dn.Ip + ":" + strconv.Itoa(dn.Port)
}

func (dn *DataNode) ToMap() interface{} {
	ret := make(map[string]interface{})
	ret["Url"] = dn.Url()
	ret["Volumes"] = dn.GetVolumeCount()
	ret["VolumeIds"] = dn.GetVolumeIds()
	ret["EcShards"] = dn.GetEcShardCount()
	ret["Max"] = dn.GetMaxVolumeCount()
	ret["Free"] = dn.FreeSpace()
	ret["PublicUrl"] = dn.PublicUrl
	return ret
}

func (dn *DataNode) ToDataNodeInfo() *master_pb.DataNodeInfo {
	m := &master_pb.DataNodeInfo{
		Id:                string(dn.Id()),
		VolumeCount:       uint64(dn.GetVolumeCount()),
		MaxVolumeCount:    uint64(dn.GetMaxVolumeCount()),
		FreeVolumeCount:   uint64(dn.FreeSpace()),
		ActiveVolumeCount: uint64(dn.GetActiveVolumeCount()),
		RemoteVolumeCount: uint64(dn.GetRemoteVolumeCount()),
	}
	for _, v := range dn.GetVolumes() {
		m.VolumeInfos = append(m.VolumeInfos, v.ToVolumeInformationMessage())
	}
	for _, ecv := range dn.GetEcShards() {
		m.EcShardInfos = append(m.EcShardInfos, ecv.ToVolumeEcShardInformationMessage())
	}
	return m
}

// GetVolumeIds returns the human readable volume ids limited to count of max 100.
func (dn *DataNode) GetVolumeIds() string {
	dn.RLock()
	defer dn.RUnlock()
	ids := make([]int, 0, len(dn.volumes))

	for k := range dn.volumes {
		ids = append(ids, int(k))
	}

	return util.HumanReadableIntsMax(100, ids...)
}
<commit_msg>nil related<commit_after>package topology

import (
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/util"
	"strconv"
	"sync"

	"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
	"github.com/chrislusf/seaweedfs/weed/storage/erasure_coding"
	"github.com/chrislusf/seaweedfs/weed/storage/needle"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/storage"
)

type DataNode struct {
	NodeImpl
	volumes      map[needle.VolumeId]storage.VolumeInfo
	Ip           string
	Port         int
	PublicUrl    string
	LastSeen     int64 // unix time in seconds
	ecShards     map[needle.VolumeId]*erasure_coding.EcVolumeInfo
	ecShardsLock sync.RWMutex
}

func NewDataNode(id string) *DataNode {
	s := &DataNode{}
	s.id = NodeId(id)
	s.nodeType = "DataNode"
	s.volumes = make(map[needle.VolumeId]storage.VolumeInfo)
	s.ecShards = make(map[needle.VolumeId]*erasure_coding.EcVolumeInfo)
	s.NodeImpl.value = s
	return s
}

func (dn *DataNode) String() string {
	dn.RLock()
	defer dn.RUnlock()
	return fmt.Sprintf("Node:%s, volumes:%v, Ip:%s, Port:%d, PublicUrl:%s", dn.NodeImpl.String(), dn.volumes, dn.Ip, dn.Port, dn.PublicUrl)
}

func (dn *DataNode) AddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChangedRO bool) {
	dn.Lock()
	defer dn.Unlock()
	return dn.doAddOrUpdateVolume(v)
}

func (dn *DataNode) doAddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChangedRO bool) {
	if oldV, ok := dn.volumes[v.Id]; !ok {
		dn.volumes[v.Id] = v
		dn.UpAdjustVolumeCountDelta(1)
		if v.IsRemote() {
			dn.UpAdjustRemoteVolumeCountDelta(1)
		}
		if !v.ReadOnly {
			dn.UpAdjustActiveVolumeCountDelta(1)
		}
		dn.UpAdjustMaxVolumeId(v.Id)
		isNew = true
	} else {
		if oldV.IsRemote() != v.IsRemote() {
			if v.IsRemote() {
				dn.UpAdjustRemoteVolumeCountDelta(1)
			}
			if oldV.IsRemote() {
				dn.UpAdjustRemoteVolumeCountDelta(-1)
			}
		}
		isChangedRO = dn.volumes[v.Id].ReadOnly != v.ReadOnly
		dn.volumes[v.Id] = v
	}
	return
}

func (dn *DataNode) UpdateVolumes(actualVolumes []storage.VolumeInfo) (newVolumes, deletedVolumes, changeRO []storage.VolumeInfo) {

	actualVolumeMap := make(map[needle.VolumeId]storage.VolumeInfo)
	for _, v := range actualVolumes {
		actualVolumeMap[v.Id] = v
	}

	dn.Lock()
	defer dn.Unlock()

	for vid, v := range dn.volumes {
		if _, ok := actualVolumeMap[vid]; !ok {
			glog.V(0).Infoln("Deleting volume id:", vid)
			delete(dn.volumes, vid)
			deletedVolumes = append(deletedVolumes, v)
			dn.UpAdjustVolumeCountDelta(-1)
			if v.IsRemote() {
				dn.UpAdjustRemoteVolumeCountDelta(-1)
			}
			if !v.ReadOnly {
				dn.UpAdjustActiveVolumeCountDelta(-1)
			}
		}
	}
	for _, v := range actualVolumes {
		isNew, isChangedRO := dn.doAddOrUpdateVolume(v)
		if isNew {
			newVolumes = append(newVolumes, v)
		}
		if isChangedRO {
			changeRO = append(changeRO, v)
		}
	}
	return
}

func (dn *DataNode) DeltaUpdateVolumes(newVolumes, deletedVolumes []storage.VolumeInfo) {
	dn.Lock()
	defer dn.Unlock()

	for _, v := range deletedVolumes {
		delete(dn.volumes, v.Id)
		dn.UpAdjustVolumeCountDelta(-1)
		if v.IsRemote() {
			dn.UpAdjustRemoteVolumeCountDelta(-1)
		}
		if !v.ReadOnly {
			dn.UpAdjustActiveVolumeCountDelta(-1)
		}
	}
	for _, v := range newVolumes {
		dn.doAddOrUpdateVolume(v)
	}
	return
}

func (dn *DataNode) GetVolumes() (ret []storage.VolumeInfo) {
	dn.RLock()
	for _, v := range dn.volumes {
		ret = append(ret, v)
	}
	dn.RUnlock()
	return ret
}

func (dn *DataNode) GetVolumesById(id needle.VolumeId) (storage.VolumeInfo, error) {
	dn.RLock()
	defer dn.RUnlock()
	vInfo, ok := dn.volumes[id]
	if ok {
		return vInfo, nil
	} else {
		return storage.VolumeInfo{}, fmt.Errorf("volumeInfo not found")
	}
}

func (dn *DataNode) GetDataCenter() *DataCenter {
	rack := dn.Parent()
	dcNode := rack.Parent()
	dcValue := dcNode.GetValue()
	return dcValue.(*DataCenter)
}

func (dn *DataNode) GetRack() *Rack {
	return dn.Parent().(*NodeImpl).value.(*Rack)
}

func (dn *DataNode) GetTopology() *Topology {
	p := dn.Parent()
	for p.Parent() != nil {
		p = p.Parent()
	}
	t := p.(*Topology)
	return t
}

func (dn *DataNode) MatchLocation(ip string, port int) bool {
	return dn.Ip == ip && dn.Port == port
}

func (dn *DataNode) Url() string {
	return dn.Ip + ":" + strconv.Itoa(dn.Port)
}

func (dn *DataNode) ToMap() interface{} {
	ret := make(map[string]interface{})
	ret["Url"] = dn.Url()
	ret["Volumes"] = dn.GetVolumeCount()
	ret["VolumeIds"] = dn.GetVolumeIds()
	ret["EcShards"] = dn.GetEcShardCount()
	ret["Max"] = dn.GetMaxVolumeCount()
	ret["Free"] = dn.FreeSpace()
	ret["PublicUrl"] = dn.PublicUrl
	return ret
}

func (dn *DataNode) ToDataNodeInfo() *master_pb.DataNodeInfo {
	m := &master_pb.DataNodeInfo{
		Id:                string(dn.Id()),
		VolumeCount:       uint64(dn.GetVolumeCount()),
		MaxVolumeCount:    uint64(dn.GetMaxVolumeCount()),
		FreeVolumeCount:   uint64(dn.FreeSpace()),
		ActiveVolumeCount: uint64(dn.GetActiveVolumeCount()),
		RemoteVolumeCount: uint64(dn.GetRemoteVolumeCount()),
	}
	for _, v := range dn.GetVolumes() {
		m.VolumeInfos = append(m.VolumeInfos, v.ToVolumeInformationMessage())
	}
	for _, ecv := range dn.GetEcShards() {
		m.EcShardInfos = append(m.EcShardInfos, ecv.ToVolumeEcShardInformationMessage())
	}
	return m
}

// GetVolumeIds returns the human readable volume ids limited to count of max 100.
func (dn *DataNode) GetVolumeIds() string {
	dn.RLock()
	defer dn.RUnlock()
	ids := make([]int, 0, len(dn.volumes))

	for k := range dn.volumes {
		ids = append(ids, int(k))
	}

	return util.HumanReadableIntsMax(100, ids...)
}
<|endoftext|>


<commit_before>package mem

import "sync"

var pools []*sync.Pool

const (
	min_size = 1024
)

func bitCount(size int) (count int) {
	for ; size > min_size; count++ {
		size = size >> 1
	}
	return
}

func init() {
	// 1KB ~ 256MB
	pools = make([]*sync.Pool, bitCount(1024*1024*256))
	for i := 0; i < len(pools); i++ {
		slotSize := 1024 << i
		pools[i] = &sync.Pool{
			New: func() interface{} {
				buffer := make([]byte, slotSize)
				return &buffer
			},
		}
	}
}

func getSlotPool(size int) *sync.Pool {
	index := bitCount(size)
	return pools[index]
}

func Allocate(size int) []byte {
	slab := *getSlotPool(size).Get().(*[]byte)
	return slab[:size]
}

func Free(buf []byte) {
	getSlotPool(cap(buf)).Put(&buf)
}
<commit_msg>testing skip memory management<commit_after>package mem

import "sync"

var pools []*sync.Pool

const (
	min_size = 1024
)

func bitCount(size int) (count int) {
	for ; size > min_size; count++ {
		size = size >> 1
	}
	return
}

func init() {
	// 1KB ~ 256MB
	pools = make([]*sync.Pool, bitCount(1024*1024*256))
	for i := 0; i < len(pools); i++ {
		slotSize := 1024 << i
		pools[i] = &sync.Pool{
			New: func() interface{} {
				buffer := make([]byte, slotSize)
				return &buffer
			},
		}
	}
}

func getSlotPool(size int) *sync.Pool {
	index := bitCount(size)
	return pools[index]
}

func Allocate(size int) []byte {
	return make([]byte, size)
	slab := *getSlotPool(size).Get().(*[]byte)
	return slab[:size]
}

func Free(buf []byte) {
	return
	getSlotPool(cap(buf)).Put(&buf)
}
<|endoftext|>


<commit_before>//
//
//
// #! /usr/bin/env ruby
//
// require 'sensu-handler'
// require 'socket'
// require 'json'
//
// class StatsdEvent < Sensu::Handler
//
//   input = JSON.parse(STDIN.read)
//   data = input['check']['output']
//   server = ''
//   port = 8125
//
//   s = UDPSocket.new
//   s.connect(server, port)
//
//   data.each_line do |metric|
//     s.send(metric, 0)
//   end
// end
<commit_msg>add statsd client configs<commit_after>// Take well-formed input in graphie format and send it to statsd
//
// LICENSE:
//   Copyright 2015 Yieldbot. <devops@yieldbot.com>
//   Released under the MIT License; see LICENSE
//   for details.

package main

import (
	"flag"
	dracky "github.com/yieldbot/sensu-yieldbot-library/src"
  "github.com/quipo/statsd"
)

func main() {

  // set commandline flags
	HostPtr := flag.String("host", "localhost" "the statsd host")
	PortPtr := flag.String("port", "8125", "the statsd port")
  ProtocolPtr := flag.String("protocol", "udp", "the protocol to connect with")

	flag.Parse()
	statsdHost := *HostPtr
	statsdPort := *PortPtr
  statsdProtocol := *ProtocolPtr

   statsdclient := statsd.NewStatsdClient(statsdHost + ":" + statsdPort)
   statsdclient.CreateSocket()
   defer stats.Close()

   sensuEvent := new(dracky.SensuEvent)
   sensuEvent = sensuEvent.AcquireSensuEvent()

   metricData := sensuEvent.Check.Output

   for i, m := range metricData {
     statsdclient.SesdEvent(m)
   }
 }
<|endoftext|>


<commit_before><commit_msg>logon.js test<commit_after><|endoftext|>


<commit_before>package gochatwork

import (
	"encoding/json"
	"time"
)

// BaseURL ChatWork API endpooint URL
const BaseURL = `https://api.chatwork.com/v1`

// Me model
type Me struct {
	AccountID        int    `json:"account_id"`
	RoomID           int    `json:"room_id"`
	Name             string `json:"name"`
	ChatworkID       string `json:"chatwork_id"`
	OrganizationID   int    `json:"organization_id"`
	OrganizationName string `json:"organization_name"`
	Department       string `json:"department"`
	Title            string `json:"title"`
	URL              string `json:"url"`
	Introduction     string `json:"introduction"`
	Mail             string `json:"mail"`
	TelOrganization  string `json:"tel_organization"`
	TelExtension     string `json:"tel_extension"`
	TelMobile        string `json:"tel_mobile"`
	Skype            string `json:"skype"`
	Facebook         string `json:"facebook"`
	Twitter          string `json:"twitter"`
	AvatarImageURL   string `json:"avatar_image_url"`
}

// Me GET "/me"
func (c *Client) Me() (me Me, err error) {
	ret, err := c.Get("/me", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &me)
	return
}

// Status model
type Status struct {
	UnreadRoomNum  int `json:"unread_room_num"`
	MentionRoomNum int `json:"mention_room_num"`
	MytaskRoomNum  int `json:"mytask_room_num"`
	UnreadNum      int `json:"unread_num"`
	MentionNum     int `json:"mention_num"`
	MyTaskNum      int `json:"mytask_num"`
}

// MyStatus GET "/my/status"
func (c *Client) MyStatus() (status Status, err error) {
	ret, err := c.Get("/my/status", nil)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &status)
	return
}

// MyTask model
type MyTask struct {
	Task
	Room struct {
		Roomid   int    `json:"room_id"`
		Name     string `json:"name"`
		IconPath string `json:"icon_path"`
	}
}

// MyTasks GET "/my/tasks"
// params keys
//  - assigned_by_account_id
//  - status: [open, done]
func (c *Client) MyTasks(params map[string]string) (tasks []MyTask, err error) {
	ret, err := c.Get("/my/tasks", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &tasks)
	return
}

// Contact model
type Contact struct {
	AccountID        int    `json:"account_id"`
	RoomID           int    `json:"room_id"`
	Name             string `json:"name"`
	ChatworkID       string `json:"chatwork_id"`
	OrganizationID   int    `json:"organization_id"`
	OrganizationName string `json:"organization_name"`
	Department       string `json:"department"`
	AvatarImageURL   string `json:"avatar_image_url"`
}

// Contacts GET "/contacts"
func (c *Client) Contacts() (contacts []Contact, err error) {
	ret, err := c.Get("/contacts", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &contacts)
	return
}

// Room model
type Room struct {
	RoomID         int    `json:"room_id"`
	Name           string `json:"name"`
	Type           string `json:"type"`
	Role           string `json:"role"`
	Sticky         bool   `json:"sticky"`
	UnreadNum      int    `json:"unread_num"`
	MentionNum     int    `json:"mention_num"`
	MytaskNum      int    `json:"mytask_num"`
	MessageNum     int    `json:"message_num"`
	FileNum        int    `json:"file_num"`
	TaskNum        int    `json:"task_num"`
	IconPath       string `json:"icon_path"`
	LastUpdateTime int64  `json:"last_update_time"`
	Description    string `json:"description"`
}

// Rooms GET "/rooms"
func (c *Client) Rooms() (rooms []Room, err error) {
	ret, err := c.Get("/rooms", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &rooms)
	return
}

// Room GET "/rooms/{room_id}"
func (c *Client) Room(roomID string) (room Room, err error) {
	ret, err := c.Get("/rooms/"+roomID, map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &room)
	return
}

// CreateRoom POST "/rooms"
// params keys
//   * name
//   * members_admin_ids
//   - description
//   - icon_preset
//   - members_member_ids
//   - members_readonly_ids
func (c *Client) CreateRoom(params map[string]string) ([]byte, error) {
	return c.Post("/rooms", params)
}

// UpdateRoom PUT "/rooms/{room_id}"
// params keys
//   - description
//   - icon_preset
//   - name
func (c *Client) UpdateRoom(roomID string, params map[string]string) ([]byte, error) {
	return c.Put("/rooms/"+roomID, params)
}

// DeleteRoom DELETE "/rooms/{room_id}"
// params key
//   * action_type: [leave, delete]
func (c *Client) DeleteRoom(roomID string, params map[string]string) ([]byte, error) {
	return c.Delete("/rooms/"+roomID, params)
}

// Member model
type Member struct {
	AccountID        int    `json:"account_id"`
	Role             string `json:"role"`
	Name             string `json:"name"`
	ChatworkID       string `json:"chatwork_id"`
	OrganizationID   int    `json:"organization_id"`
	OrganizationName string `json:"organization_name"`
	Department       string `json:"department"`
	AvatarImageURL   string `json:"avatar_image_url"`
}

// RoomMembers GET "/rooms/{room_id}/members"
func (c *Client) RoomMembers(roomID string) (members []Member, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/members", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &members)
	return
}

// UpdateRoomMembers PUT "/rooms/{room_id}/members"
// params keys
//   * members_admin_ids
//   - members_member_ids
//   - members_readonly_ids
func (c *Client) UpdateRoomMembers(roomID string, params map[string]string) ([]byte, error) {
	return c.Put("/rooms/"+roomID+"/members", params)
}

// Account model
type Account struct {
	AccountID      int    `json:"account_id"`
	Name           string `json:"name"`
	AvatarImageURL string `json:"avatar_image_url"`
}

// Message model
type Message struct {
	MessageID  int     `json:"message_id"`
	Account    Account `json:"account"`
	Body       string  `json:"body"`
	SendTime   int64   `json:"send_time"`
	UpdateTime int64   `json:"update_time"`
}

// SendDate time.Time representation of SendTime
func (m Message) SendDate() time.Time {
	return time.Unix(m.SendTime, 0)
}

// UpdateDate time.Time representation of UpdateTime
func (m Message) UpdateDate() time.Time {
	return time.Unix(m.UpdateTime, 0)
}

// Messages slice of Message
type Messages []Message

// RoomMessages GET "/rooms/{room_id}/messages"
func (c *Client) RoomMessages(roomID string, params map[string]string) (msgs Messages, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/messages", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &msgs)
	return
}

// PostRoomMessage POST "/rooms/{room_id}/messages"
func (c *Client) PostRoomMessage(roomID string, body string) ([]byte, error) {
	return c.Post("/rooms/"+roomID+"/messages", map[string]string{"body": body})
}

// RoomMessage GET "/rooms/{room_id}/messages/{message_id}"
func (c *Client) RoomMessage(roomID, messageID string) (message Message, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/messages/"+messageID, map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &message)
	return
}

// Task model
type Task struct {
	TaskID            int     `json:"task_id"`
	Account           Account `json:"account"`
	AssignedByAccount Account `json:"assigned_by_account"`
	MessageID         int     `json:"message_id"`
	Body              string  `json:"body"`
	LimitTime         int64   `json:"limit_time"`
	Status            string  `json:"status"`
}

// LimitDate time.Time representation of LimitTime
func (t Task) LimitDate() time.Time {
	return time.Unix(t.LimitTime, 0)
}

// RoomTasks GET "/rooms/{room_id}/tasks"
// params keys
//  - account_id
//  - assigned_by_account_id
//  - status: [open, done]
func (c *Client) RoomTasks(roomID string, params map[string]string) (tasks []Task, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/tasks", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &tasks)
	return
}

// PostRoomTask POST "/rooms/{room_id}/tasks"
// params keys
//   * body
//   * to_ids
//   - limit
func (c *Client) PostRoomTask(roomID string, params map[string]string) ([]byte, error) {
	return c.Post("/rooms/"+roomID+"/tasks", params)
}

// RoomTask GET "/rooms/{room_id}/tasks/tasks_id"
func (c *Client) RoomTask(roomID, taskID string) (task Task, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/tasks/"+taskID, map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &task)
	return
}

// File model
type File struct {
	FileID      int     `json:"file_id"`
	Account     Account `json:"account"`
	MessageID   int     `json:"message_id"`
	Filename    string  `json:"filename"`
	Filesize    int     `json:"filesize"`
	UploadTime  int64   `json:"upload_time"`
	DownloadURL string  `json:"download_url"`
}

// UploadDate time.Time representation of UploadTime
func (f File) UploadDate() time.Time {
	return time.Unix(f.UploadTime, 0)
}

// RoomFiles GET "/rooms/{room_id}/files/"
// params key
//   - account_id
func (c *Client) RoomFiles(roomID string, params map[string]string) (files []File, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/files", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &files)
	return
}

// RoomFile GET "/rooms/{room_id}/files/{file_id}"
// params key
//   - create_download_url: ["0", "1"]
func (c *Client) RoomFile(roomID, fileID string, params map[string]string) (file File, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/files/"+fileID, params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &file)
	return
}

// RateLimit model
type RateLimit struct {
	Limit     int
	Remaining int
	ResetTime int64
}

// ResetDate time.Time representation of ResetTime
func (r RateLimit) ResetDate() time.Time {
	return time.Unix(r.ResetTime, 0)
}

// RateLimit returns rate limit
func (c *Client) RateLimit() *RateLimit {
	if c.latestRateLimit == nil {
		// When API is not called even once, call API and get RateLimit in response header
		c.Me()
	}
	return c.latestRateLimit
}
<commit_msg>Update API version (v2)<commit_after>package gochatwork

import (
	"encoding/json"
	"time"
)

// BaseURL ChatWork API endpooint URL
const BaseURL = `https://api.chatwork.com/v2`

// Me model
type Me struct {
	AccountID        int    `json:"account_id"`
	RoomID           int    `json:"room_id"`
	Name             string `json:"name"`
	ChatworkID       string `json:"chatwork_id"`
	OrganizationID   int    `json:"organization_id"`
	OrganizationName string `json:"organization_name"`
	Department       string `json:"department"`
	Title            string `json:"title"`
	URL              string `json:"url"`
	Introduction     string `json:"introduction"`
	Mail             string `json:"mail"`
	TelOrganization  string `json:"tel_organization"`
	TelExtension     string `json:"tel_extension"`
	TelMobile        string `json:"tel_mobile"`
	Skype            string `json:"skype"`
	Facebook         string `json:"facebook"`
	Twitter          string `json:"twitter"`
	AvatarImageURL   string `json:"avatar_image_url"`
}

// Me GET "/me"
func (c *Client) Me() (me Me, err error) {
	ret, err := c.Get("/me", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &me)
	return
}

// Status model
type Status struct {
	UnreadRoomNum  int `json:"unread_room_num"`
	MentionRoomNum int `json:"mention_room_num"`
	MytaskRoomNum  int `json:"mytask_room_num"`
	UnreadNum      int `json:"unread_num"`
	MentionNum     int `json:"mention_num"`
	MyTaskNum      int `json:"mytask_num"`
}

// MyStatus GET "/my/status"
func (c *Client) MyStatus() (status Status, err error) {
	ret, err := c.Get("/my/status", nil)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &status)
	return
}

// MyTask model
type MyTask struct {
	Task
	Room struct {
		Roomid   int    `json:"room_id"`
		Name     string `json:"name"`
		IconPath string `json:"icon_path"`
	}
}

// MyTasks GET "/my/tasks"
// params keys
//  - assigned_by_account_id
//  - status: [open, done]
func (c *Client) MyTasks(params map[string]string) (tasks []MyTask, err error) {
	ret, err := c.Get("/my/tasks", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &tasks)
	return
}

// Contact model
type Contact struct {
	AccountID        int    `json:"account_id"`
	RoomID           int    `json:"room_id"`
	Name             string `json:"name"`
	ChatworkID       string `json:"chatwork_id"`
	OrganizationID   int    `json:"organization_id"`
	OrganizationName string `json:"organization_name"`
	Department       string `json:"department"`
	AvatarImageURL   string `json:"avatar_image_url"`
}

// Contacts GET "/contacts"
func (c *Client) Contacts() (contacts []Contact, err error) {
	ret, err := c.Get("/contacts", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &contacts)
	return
}

// Room model
type Room struct {
	RoomID         int    `json:"room_id"`
	Name           string `json:"name"`
	Type           string `json:"type"`
	Role           string `json:"role"`
	Sticky         bool   `json:"sticky"`
	UnreadNum      int    `json:"unread_num"`
	MentionNum     int    `json:"mention_num"`
	MytaskNum      int    `json:"mytask_num"`
	MessageNum     int    `json:"message_num"`
	FileNum        int    `json:"file_num"`
	TaskNum        int    `json:"task_num"`
	IconPath       string `json:"icon_path"`
	LastUpdateTime int64  `json:"last_update_time"`
	Description    string `json:"description"`
}

// Rooms GET "/rooms"
func (c *Client) Rooms() (rooms []Room, err error) {
	ret, err := c.Get("/rooms", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &rooms)
	return
}

// Room GET "/rooms/{room_id}"
func (c *Client) Room(roomID string) (room Room, err error) {
	ret, err := c.Get("/rooms/"+roomID, map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &room)
	return
}

// CreateRoom POST "/rooms"
// params keys
//   * name
//   * members_admin_ids
//   - description
//   - icon_preset
//   - members_member_ids
//   - members_readonly_ids
func (c *Client) CreateRoom(params map[string]string) ([]byte, error) {
	return c.Post("/rooms", params)
}

// UpdateRoom PUT "/rooms/{room_id}"
// params keys
//   - description
//   - icon_preset
//   - name
func (c *Client) UpdateRoom(roomID string, params map[string]string) ([]byte, error) {
	return c.Put("/rooms/"+roomID, params)
}

// DeleteRoom DELETE "/rooms/{room_id}"
// params key
//   * action_type: [leave, delete]
func (c *Client) DeleteRoom(roomID string, params map[string]string) ([]byte, error) {
	return c.Delete("/rooms/"+roomID, params)
}

// Member model
type Member struct {
	AccountID        int    `json:"account_id"`
	Role             string `json:"role"`
	Name             string `json:"name"`
	ChatworkID       string `json:"chatwork_id"`
	OrganizationID   int    `json:"organization_id"`
	OrganizationName string `json:"organization_name"`
	Department       string `json:"department"`
	AvatarImageURL   string `json:"avatar_image_url"`
}

// RoomMembers GET "/rooms/{room_id}/members"
func (c *Client) RoomMembers(roomID string) (members []Member, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/members", map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &members)
	return
}

// UpdateRoomMembers PUT "/rooms/{room_id}/members"
// params keys
//   * members_admin_ids
//   - members_member_ids
//   - members_readonly_ids
func (c *Client) UpdateRoomMembers(roomID string, params map[string]string) ([]byte, error) {
	return c.Put("/rooms/"+roomID+"/members", params)
}

// Account model
type Account struct {
	AccountID      int    `json:"account_id"`
	Name           string `json:"name"`
	AvatarImageURL string `json:"avatar_image_url"`
}

// Message model
type Message struct {
	MessageID  int     `json:"message_id"`
	Account    Account `json:"account"`
	Body       string  `json:"body"`
	SendTime   int64   `json:"send_time"`
	UpdateTime int64   `json:"update_time"`
}

// SendDate time.Time representation of SendTime
func (m Message) SendDate() time.Time {
	return time.Unix(m.SendTime, 0)
}

// UpdateDate time.Time representation of UpdateTime
func (m Message) UpdateDate() time.Time {
	return time.Unix(m.UpdateTime, 0)
}

// Messages slice of Message
type Messages []Message

// RoomMessages GET "/rooms/{room_id}/messages"
func (c *Client) RoomMessages(roomID string, params map[string]string) (msgs Messages, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/messages", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &msgs)
	return
}

// PostRoomMessage POST "/rooms/{room_id}/messages"
func (c *Client) PostRoomMessage(roomID string, body string) ([]byte, error) {
	return c.Post("/rooms/"+roomID+"/messages", map[string]string{"body": body})
}

// RoomMessage GET "/rooms/{room_id}/messages/{message_id}"
func (c *Client) RoomMessage(roomID, messageID string) (message Message, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/messages/"+messageID, map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &message)
	return
}

// Task model
type Task struct {
	TaskID            int     `json:"task_id"`
	Account           Account `json:"account"`
	AssignedByAccount Account `json:"assigned_by_account"`
	MessageID         int     `json:"message_id"`
	Body              string  `json:"body"`
	LimitTime         int64   `json:"limit_time"`
	Status            string  `json:"status"`
}

// LimitDate time.Time representation of LimitTime
func (t Task) LimitDate() time.Time {
	return time.Unix(t.LimitTime, 0)
}

// RoomTasks GET "/rooms/{room_id}/tasks"
// params keys
//  - account_id
//  - assigned_by_account_id
//  - status: [open, done]
func (c *Client) RoomTasks(roomID string, params map[string]string) (tasks []Task, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/tasks", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &tasks)
	return
}

// PostRoomTask POST "/rooms/{room_id}/tasks"
// params keys
//   * body
//   * to_ids
//   - limit
func (c *Client) PostRoomTask(roomID string, params map[string]string) ([]byte, error) {
	return c.Post("/rooms/"+roomID+"/tasks", params)
}

// RoomTask GET "/rooms/{room_id}/tasks/tasks_id"
func (c *Client) RoomTask(roomID, taskID string) (task Task, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/tasks/"+taskID, map[string]string{})
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &task)
	return
}

// File model
type File struct {
	FileID      int     `json:"file_id"`
	Account     Account `json:"account"`
	MessageID   int     `json:"message_id"`
	Filename    string  `json:"filename"`
	Filesize    int     `json:"filesize"`
	UploadTime  int64   `json:"upload_time"`
	DownloadURL string  `json:"download_url"`
}

// UploadDate time.Time representation of UploadTime
func (f File) UploadDate() time.Time {
	return time.Unix(f.UploadTime, 0)
}

// RoomFiles GET "/rooms/{room_id}/files/"
// params key
//   - account_id
func (c *Client) RoomFiles(roomID string, params map[string]string) (files []File, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/files", params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &files)
	return
}

// RoomFile GET "/rooms/{room_id}/files/{file_id}"
// params key
//   - create_download_url: ["0", "1"]
func (c *Client) RoomFile(roomID, fileID string, params map[string]string) (file File, err error) {
	ret, err := c.Get("/rooms/"+roomID+"/files/"+fileID, params)
	if err != nil {
		return
	}
	err = json.Unmarshal(ret, &file)
	return
}

// RateLimit model
type RateLimit struct {
	Limit     int
	Remaining int
	ResetTime int64
}

// ResetDate time.Time representation of ResetTime
func (r RateLimit) ResetDate() time.Time {
	return time.Unix(r.ResetTime, 0)
}

// RateLimit returns rate limit
func (c *Client) RateLimit() *RateLimit {
	if c.latestRateLimit == nil {
		// When API is not called even once, call API and get RateLimit in response header
		c.Me()
	}
	return c.latestRateLimit
}
<|endoftext|>


<commit_before>package telebot

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// Raw lets you call any method of Bot API manually.
func (b *Bot) Raw(method string, payload interface{}) ([]byte, error) {
	url := b.URL + "/bot" + b.Token + "/" + method

	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(payload); err != nil {
		return []byte{}, wrapSystem(err)
	}

	resp, err := b.client.Post(url, "application/json", &buf)
	if err != nil {
		return []byte{}, errors.Wrap(err, "http.Post failed")
	}
	resp.Close = true
	defer resp.Body.Close()

	json, err := ioutil.ReadAll(resp.Body)
	fmt.Println(string(json))
	data := apiErrorRx.FindStringSubmatch(string(json))
	if err != nil {
		return []byte{}, wrapSystem(err)
	}

	if data == nil {
		fmt.Printf("ok!\n")
		return json, nil
	}

	description := data[2]
	code,_ := strconv.Atoi(data[0])
	switch description{
	case ErrUnauthorized.ʔ():
		err = ErrUnauthorized
	case ErrToForwardNotFound.ʔ():
		err = ErrToForwardNotFound
	case ErrToReplyNotFound.ʔ():
		err = ErrToReplyNotFound
	case ErrMessageTooLong.ʔ():
		err = ErrMessageTooLong
	case ErrBlockedByUsr.ʔ():
		err = ErrBlockedByUsr
	case ErrToDeleteNotFound.ʔ():
		err = ErrToDeleteNotFound
	case ErrEmptyMessage.ʔ():
		err = ErrEmptyMessage
	case ErrEmptyText.ʔ():
		err = ErrEmptyText
	case ErrEmptyChatID.ʔ():
		err = ErrEmptyChatID
	case ErrNotFoundChat.ʔ():
		err = ErrNotFoundChat
	case ErrMessageNotModified.ʔ():
		err = ErrMessageNotModified
	case ErrNoRightsToRestrict.ʔ():
		err = ErrNoRightsToRestrict
	case ErrNoRightsToSendMsg.ʔ():
		err = ErrNoRightsToSendMsg
	case ErrNoRightsToSendPhoto.ʔ():
		err = ErrNoRightsToSendPhoto
	case ErrNoRightsToSendStickers.ʔ():
		err = ErrNoRightsToSendStickers
	case ErrNoRightsToSendGifs.ʔ():
		err = ErrNoRightsToSendGifs
	case ErrNoRightsToDelete.ʔ():
		err = ErrNoRightsToDelete
	case ErrKickingChatOwner.ʔ():
		err = ErrKickingChatOwner
	case ErrInteractKickedG.ʔ():
		err = ErrKickingChatOwner
	case ErrInteractKickedSprG.ʔ():
		err = ErrInteractKickedSprG
	case ErrWrongTypeOfContent.ʔ():
		err = ErrWrongTypeOfContent
	case ErrCantGetHTTPurlContent.ʔ():
		err = ErrCantGetHTTPurlContent
	case ErrWrongRemoteFileID.ʔ():
		err = ErrWrongRemoteFileID
	case ErrFileIdTooShort.ʔ():
		err = ErrFileIdTooShort
	case ErrWrongRemoteFileIDsymbol.ʔ():
		err = ErrWrongRemoteFileIDsymbol
	case ErrWrongFileIdentifier.ʔ():
		err = ErrWrongFileIdentifier
	case ErrTooLarge.ʔ():
		err = ErrTooLarge
	case ErrWrongPadding.ʔ():
		err = ErrWrongPadding
	case ErrImageProcess.ʔ():
		err = ErrImageProcess
	case ErrWrongStickerpack.ʔ():
		err = ErrWrongStickerpack
	default:
		err = fmt.Errorf("unknown api error: %s (%d)", description, code)
	}
	if err != nil {
		return []byte{}, err
	}
	return json, nil

}

func addFileToWriter(writer *multipart.Writer,
	filename, field string, file interface{}) error {

	var reader io.Reader
	if r, ok := file.(io.Reader); ok {
		reader = r
	} else if path, ok := file.(string); ok {
		f, err := os.Open(path)
		if err != nil {
			return err
		}
		defer f.Close()
		reader = f
	} else {
		return errors.Errorf("File for field `%v` should be an io.ReadCloser or string", field)
	}

	part, err := writer.CreateFormFile(field, filename)
	if err != nil {
		return err
	}

	_, err = io.Copy(part, reader)
	return err
}

func (b *Bot) sendFiles(method string, files map[string]File,
	params map[string]string) ([]byte, error) {

	body := &bytes.Buffer{}
	rawFiles := map[string]interface{}{}

	for name, f := range files {
		switch {
		case f.InCloud():
			params[name] = f.FileID
		case f.FileURL != "":
			params[name] = f.FileURL
		case f.OnDisk():
			rawFiles[name] = f.FileLocal
		case f.FileReader != nil:
			rawFiles[name] = f.FileReader
		default:
			return nil, errors.Errorf("sendFiles: File for field %s doesn't exist", name)
		}
	}

	if len(rawFiles) == 0 {
		return b.Raw(method, params)
	}

	writer := multipart.NewWriter(body)

	for field, file := range rawFiles {
		if err := addFileToWriter(writer, params["file_name"], field, file); err != nil {
			return nil, wrapSystem(err)
		}
	}

	for field, value := range params {
		if err := writer.WriteField(field, value); err != nil {
			return nil, wrapSystem(err)
		}
	}

	if err := writer.Close(); err != nil {
		return nil, wrapSystem(err)
	}

	url := b.URL + "/bot" + b.Token + "/" + method
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		return nil, wrapSystem(err)
	}

	req.Header.Add("Content-Type", writer.FormDataContentType())

	resp, err := b.client.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "http.Post failed")
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusInternalServerError {
		return nil, errors.New("api error: internal server error")
	}

	json, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, wrapSystem(err)
	}

	return json, nil
}

func (b *Bot) sendObject(f *File, what string, params map[string]string, files map[string]File) (*Message, error) {
	sendWhat := "send" + strings.Title(what)

	if what == "videoNote" {
		what = "video_note"
	}

	sendFiles := map[string]File{what: *f}
	for k, v := range files {
		sendFiles[k] = v
	}

	respJSON, err := b.sendFiles(sendWhat, sendFiles, params)
	if err != nil {
		return nil, err
	}

	return extractMsgResponse(respJSON)
}

func (b *Bot) getMe() (*User, error) {
	meJSON, err := b.Raw("getMe", nil)
	if err != nil {
		return nil, err
	}

	var botInfo struct {
		Ok          bool
		Result      *User
		Description string
	}

	err = json.Unmarshal(meJSON, &botInfo)
	if err != nil {
		return nil, errors.Wrap(err, "bad response json")
	}

	if !botInfo.Ok {
		return nil, errors.Errorf("api error: %s", botInfo.Description)
	}

	return botInfo.Result, nil

}

func (b *Bot) getUpdates(offset int, timeout time.Duration) (upd []Update, err error) {
	params := map[string]string{
		"offset":  strconv.Itoa(offset),
		"timeout": strconv.Itoa(int(timeout / time.Second)),
	}
	updatesJSON, errCommand := b.Raw("getUpdates", params)
	if errCommand != nil {
		err = errCommand
		return

	}
	var updatesReceived struct {
		Ok          bool
		Result      []Update
		Description string
	}

	err = json.Unmarshal(updatesJSON, &updatesReceived)
	if err != nil {
		err = errors.Wrap(err, "bad response json")
		return
	}

	if !updatesReceived.Ok {
		err = errors.Errorf("api error: %s", updatesReceived.Description)
		return
	}

	return updatesReceived.Result, nil
}<commit_msg>errors: removed excessive debug statements<commit_after>package telebot

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"
)

// Raw lets you call any method of Bot API manually.
func (b *Bot) Raw(method string, payload interface{}) ([]byte, error) {
	url := b.URL + "/bot" + b.Token + "/" + method

	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(payload); err != nil {
		return []byte{}, wrapSystem(err)
	}

	resp, err := b.client.Post(url, "application/json", &buf)
	if err != nil {
		return []byte{}, errors.Wrap(err, "http.Post failed")
	}
	resp.Close = true
	defer resp.Body.Close()

	json, err := ioutil.ReadAll(resp.Body)
	data := apiErrorRx.FindStringSubmatch(string(json))
	if err != nil {
		return []byte{}, wrapSystem(err)
	}

	if data == nil {
		return json, nil
	}

	description := data[2]
	code,_ := strconv.Atoi(data[0])
	switch description{
	case ErrUnauthorized.ʔ():
		err = ErrUnauthorized
	case ErrToForwardNotFound.ʔ():
		err = ErrToForwardNotFound
	case ErrToReplyNotFound.ʔ():
		err = ErrToReplyNotFound
	case ErrMessageTooLong.ʔ():
		err = ErrMessageTooLong
	case ErrBlockedByUsr.ʔ():
		err = ErrBlockedByUsr
	case ErrToDeleteNotFound.ʔ():
		err = ErrToDeleteNotFound
	case ErrEmptyMessage.ʔ():
		err = ErrEmptyMessage
	case ErrEmptyText.ʔ():
		err = ErrEmptyText
	case ErrEmptyChatID.ʔ():
		err = ErrEmptyChatID
	case ErrNotFoundChat.ʔ():
		err = ErrNotFoundChat
	case ErrMessageNotModified.ʔ():
		err = ErrMessageNotModified
	case ErrNoRightsToRestrict.ʔ():
		err = ErrNoRightsToRestrict
	case ErrNoRightsToSendMsg.ʔ():
		err = ErrNoRightsToSendMsg
	case ErrNoRightsToSendPhoto.ʔ():
		err = ErrNoRightsToSendPhoto
	case ErrNoRightsToSendStickers.ʔ():
		err = ErrNoRightsToSendStickers
	case ErrNoRightsToSendGifs.ʔ():
		err = ErrNoRightsToSendGifs
	case ErrNoRightsToDelete.ʔ():
		err = ErrNoRightsToDelete
	case ErrKickingChatOwner.ʔ():
		err = ErrKickingChatOwner
	case ErrInteractKickedG.ʔ():
		err = ErrKickingChatOwner
	case ErrInteractKickedSprG.ʔ():
		err = ErrInteractKickedSprG
	case ErrWrongTypeOfContent.ʔ():
		err = ErrWrongTypeOfContent
	case ErrCantGetHTTPurlContent.ʔ():
		err = ErrCantGetHTTPurlContent
	case ErrWrongRemoteFileID.ʔ():
		err = ErrWrongRemoteFileID
	case ErrFileIdTooShort.ʔ():
		err = ErrFileIdTooShort
	case ErrWrongRemoteFileIDsymbol.ʔ():
		err = ErrWrongRemoteFileIDsymbol
	case ErrWrongFileIdentifier.ʔ():
		err = ErrWrongFileIdentifier
	case ErrTooLarge.ʔ():
		err = ErrTooLarge
	case ErrWrongPadding.ʔ():
		err = ErrWrongPadding
	case ErrImageProcess.ʔ():
		err = ErrImageProcess
	case ErrWrongStickerpack.ʔ():
		err = ErrWrongStickerpack
	default:
		err = fmt.Errorf("unknown api error: %s (%d)", description, code)
	}
	if err != nil {
		return []byte{}, err
	}
	return json, nil

}

func addFileToWriter(writer *multipart.Writer,
	filename, field string, file interface{}) error {

	var reader io.Reader
	if r, ok := file.(io.Reader); ok {
		reader = r
	} else if path, ok := file.(string); ok {
		f, err := os.Open(path)
		if err != nil {
			return err
		}
		defer f.Close()
		reader = f
	} else {
		return errors.Errorf("File for field `%v` should be an io.ReadCloser or string", field)
	}

	part, err := writer.CreateFormFile(field, filename)
	if err != nil {
		return err
	}

	_, err = io.Copy(part, reader)
	return err
}

func (b *Bot) sendFiles(method string, files map[string]File,
	params map[string]string) ([]byte, error) {

	body := &bytes.Buffer{}
	rawFiles := map[string]interface{}{}

	for name, f := range files {
		switch {
		case f.InCloud():
			params[name] = f.FileID
		case f.FileURL != "":
			params[name] = f.FileURL
		case f.OnDisk():
			rawFiles[name] = f.FileLocal
		case f.FileReader != nil:
			rawFiles[name] = f.FileReader
		default:
			return nil, errors.Errorf("sendFiles: File for field %s doesn't exist", name)
		}
	}

	if len(rawFiles) == 0 {
		return b.Raw(method, params)
	}

	writer := multipart.NewWriter(body)

	for field, file := range rawFiles {
		if err := addFileToWriter(writer, params["file_name"], field, file); err != nil {
			return nil, wrapSystem(err)
		}
	}

	for field, value := range params {
		if err := writer.WriteField(field, value); err != nil {
			return nil, wrapSystem(err)
		}
	}

	if err := writer.Close(); err != nil {
		return nil, wrapSystem(err)
	}

	url := b.URL + "/bot" + b.Token + "/" + method
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		return nil, wrapSystem(err)
	}

	req.Header.Add("Content-Type", writer.FormDataContentType())

	resp, err := b.client.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "http.Post failed")
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusInternalServerError {
		return nil, errors.New("api error: internal server error")
	}

	json, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, wrapSystem(err)
	}

	return json, nil
}

func (b *Bot) sendObject(f *File, what string, params map[string]string, files map[string]File) (*Message, error) {
	sendWhat := "send" + strings.Title(what)

	if what == "videoNote" {
		what = "video_note"
	}

	sendFiles := map[string]File{what: *f}
	for k, v := range files {
		sendFiles[k] = v
	}

	respJSON, err := b.sendFiles(sendWhat, sendFiles, params)
	if err != nil {
		return nil, err
	}

	return extractMsgResponse(respJSON)
}

func (b *Bot) getMe() (*User, error) {
	meJSON, err := b.Raw("getMe", nil)
	if err != nil {
		return nil, err
	}

	var botInfo struct {
		Ok          bool
		Result      *User
		Description string
	}

	err = json.Unmarshal(meJSON, &botInfo)
	if err != nil {
		return nil, errors.Wrap(err, "bad response json")
	}

	if !botInfo.Ok {
		return nil, errors.Errorf("api error: %s", botInfo.Description)
	}

	return botInfo.Result, nil

}

func (b *Bot) getUpdates(offset int, timeout time.Duration) (upd []Update, err error) {
	params := map[string]string{
		"offset":  strconv.Itoa(offset),
		"timeout": strconv.Itoa(int(timeout / time.Second)),
	}
	updatesJSON, errCommand := b.Raw("getUpdates", params)
	if errCommand != nil {
		err = errCommand
		return

	}
	var updatesReceived struct {
		Ok          bool
		Result      []Update
		Description string
	}

	err = json.Unmarshal(updatesJSON, &updatesReceived)
	if err != nil {
		err = errors.Wrap(err, "bad response json")
		return
	}

	if !updatesReceived.Ok {
		err = errors.Errorf("api error: %s", updatesReceived.Description)
		return
	}

	return updatesReceived.Result, nil
}<|endoftext|>