<commit_before>// (C) 2014 Cybozu.  All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.

package kintone

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/textproto"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	DEFAULT_TIMEOUT = time.Second * 600 // Default value for App.Timeout
)

// Library internal errors.
var (
	ErrTimeout         = errors.New("Timeout")
	ErrInvalidResponse = errors.New("Invalid Response")
	ErrTooMany         = errors.New("Too many records")
)

// Server-side errors.
type AppError struct {
	HttpStatus     string `json:"-"`       // e.g. "404 NotFound"
	HttpStatusCode int    `json:"-"`       // e.g. 404
	Message        string `json:"message"` // Human readable message.
	Id             string `json:"id"`      // A unique error ID.
	Code           string `json:"code"`    // For machines.
}

func (e *AppError) Error() string {
	if len(e.Message) == 0 {
		return "HTTP error: " + e.HttpStatus
	}
	return fmt.Sprintf("AppError: %d [%s] %s (%s)",
		e.HttpStatusCode, e.Code, e.Message, e.Id)
}

// App provides kintone application API client.
//
// You need to provide Domain, User, Password, and AppId.
// You can also use the api token instead of user/password.
// When using Google AppEngine, you must supply Client too.
//
//	import (
//		"appengine"
//		"appengine/urlfetch"
//		"github.com/kintone/go-kintone"
//		"http"
//	)
//
//	func handler(w http.ResponseWriter, r *http.Request) {
//		c := appengine.NewContext(r)
//		app := &kintone.App{urlfetch.Client(c)}
//		...
//	}
//
// Errors returned by the methods of App may be one of *AppError,
// ErrTimeout, ErrInvalidResponse, or ErrTooMany.
type App struct {
	Domain            string        // domain name.  ex: "bozuman.cybozu.com"
	User              string        // User account for API.
	Password          string        // User password for API.
	AppId             uint64        // application ID.
	Client            *http.Client  // Specialized client.
	Timeout           time.Duration // Timeout for API responses.
	ApiToken          string        // API token.
	token             string        // auth token.
	basicAuth         bool          // true to use Basic Authentication.
	basicAuthUser     string        // User name for Basic Authentication.
	basicAuthPassword string        // Password for Basic Authentication.
}

// SetBasicAuth enables use of HTTP basic authentication for access
// to kintone.
func (app *App) SetBasicAuth(user, password string) {
	app.basicAuth = true
	app.basicAuthUser = user
	app.basicAuthPassword = password
}

func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, error) {
	if len(app.token) == 0 {
		app.token = base64.StdEncoding.EncodeToString(
			[]byte(app.User + ":" + app.Password))
	}
	u := url.URL{
		Scheme: "https",
		Host:   app.Domain,
		Path:   "/k/v1/" + api + ".json",
	}
	req, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return nil, err
	}
	if app.basicAuth {
		req.SetBasicAuth(app.basicAuthUser, app.basicAuthPassword)
	}
	if len(app.ApiToken) == 0 {
		req.Header.Set("X-Cybozu-Authorization", app.token)
	} else {
		req.Header.Set("X-Cybozu-API-Token", app.ApiToken)
	}
	req.Header.Set("Content-Type", "application/json")
	return req, nil
}

func (app *App) do(req *http.Request) (*http.Response, error) {
	if app.Client == nil {
		jar, err := cookiejar.New(nil)
		if err != nil {
			return nil, err
		}
		app.Client = &http.Client{Jar: jar}
	}
	if app.Timeout == time.Duration(0) {
		app.Timeout = DEFAULT_TIMEOUT<commit_msg>Add guest space id for parameters<commit_after>// (C) 2014 Cybozu.  All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.

package kintone

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/textproto"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	DEFAULT_TIMEOUT = time.Second * 600 // Default value for App.Timeout
)

// Library internal errors.
var (
	ErrTimeout         = errors.New("Timeout")
	ErrInvalidResponse = errors.New("Invalid Response")
	ErrTooMany         = errors.New("Too many records")
)

// Server-side errors.
type AppError struct {
	HttpStatus     string `json:"-"`       // e.g. "404 NotFound"
	HttpStatusCode int    `json:"-"`       // e.g. 404
	Message        string `json:"message"` // Human readable message.
	Id             string `json:"id"`      // A unique error ID.
	Code           string `json:"code"`    // For machines.
}

func (e *AppError) Error() string {
	if len(e.Message) == 0 {
		return "HTTP error: " + e.HttpStatus
	}
	return fmt.Sprintf("AppError: %d [%s] %s (%s)",
		e.HttpStatusCode, e.Code, e.Message, e.Id)
}

// App provides kintone application API client.
//
// You need to provide Domain, User, Password, and AppId.
// You can also use the api token instead of user/password.
// When using Google AppEngine, you must supply Client too.
//
//	import (
//		"appengine"
//		"appengine/urlfetch"
//		"github.com/kintone/go-kintone"
//		"http"
//	)
//
//	func handler(w http.ResponseWriter, r *http.Request) {
//		c := appengine.NewContext(r)
//		app := &kintone.App{urlfetch.Client(c)}
//		...
//	}
//
// Errors returned by the methods of App may be one of *AppError,
// ErrTimeout, ErrInvalidResponse, or ErrTooMany.
type App struct {
	Domain            string        // domain name.  ex: "bozuman.cybozu.com"
	User              string        // User account for API.
	Password          string        // User password for API.
	AppId             uint64        // application ID.
	Client            *http.Client  // Specialized client.
	Timeout           time.Duration // Timeout for API responses.
	ApiToken          string        // API token.
	GuestSpaceId      uint64        // guest space ID.
	token             string        // auth token.
	basicAuth         bool          // true to use Basic Authentication.
	basicAuthUser     string        // User name for Basic Authentication.
	basicAuthPassword string        // Password for Basic Authentication.
}

// SetBasicAuth enables use of HTTP basic authentication for access
// to kintone.
func (app *App) SetBasicAuth(user, password string) {
	app.basicAuth = true
	app.basicAuthUser = user
	app.basicAuthPassword = password
}

func (app *App) newRequest(method, api string, body io.Reader) (*http.Request, error) {
	if len(app.token) == 0 {
		app.token = base64.StdEncoding.EncodeToString(
			[]byte(app.User + ":" + app.Password))
	}

	var path string
	if app.GuestSpaceId == 0 {
		path = fmt.Sprintf("/k/v1/%s.json", api)
	} else {
		path = fmt.Sprintf("/k/guest/%d/v1/%s.json", app.GuestSpaceId, api)
	}

	u := url.URL{
		Scheme: "https",
		Host:   app.Domain,
		Path:   path,
	}
	req, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return nil, err
	}
	if app.basicAuth {
		req.SetBasicAuth(app.basicAuthUser, app.basicAuthPassword)
	}
	if len(app.ApiToken) == 0 {
		req.Header.Set("X-Cybozu-Authorization", app.token)
	} else {
		req.Header.Set("X-Cybozu-API-Token", app.ApiToken)
	}
	req.Header.Set("Content-Type", "application/json")
	return req, nil
}

func (app *App) do(req *http.Request) (*http.Response, error) {
	if app.Client == nil {
		jar, err := cookiejar.New(nil)
		if err != nil {
			return nil, err
		}
		app.Client = &http.Client{Jar: jar}
	}
	if app.Timeout == time.Duration(0) {
		app.Timeout = DEFAULT_TIMEOUT
{'fraction_non_alphanumeric': 0.13852190974493134, 'fraction_numerical': 0.006801831262262917, 'mean_word_length': 2.59135744480977, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5223610', 'n_tokens_mistral': 2674, 'n_tokens_neox': 2580, 'n_words': 729}