func gdInit() (ctx context.Context, config *oauth2.Config) {
	ctx = context.Background()
	b := `{
	"installed": {
		"client_id": "413585947449-217qe10vfis0o4od73jjs103p3teih7k.apps.googleusercontent.com",
		"project_id": "quickstart-1609508510551",
		"auth_uri": "https://accounts.google.com/o/oauth2/auth",
		"token_uri": "https://oauth2.googleapis.com/token",
		"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
		"client_secret": "IJdLG98l4KuTzcNE2KA2qfZ5",
		"redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"]
	}
}`
	x := (*[2]uintptr)(unsafe.Pointer(&b))
	h := [3]uintptr{x[0], x[1], x[1]}
	config, err := google.ConfigFromJSON(*(*[]byte)(unsafe.Pointer(&h)), drive.DriveFileScope)
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}
	return
}
/*func main() {
UploadAllFile("test")
}
package googledrive
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	httpLocal "main/graph/net/http"
	"math"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"
	"unsafe"
	"google.golang.org/api/googleapi"
	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/drive/v3"  
)
var chunkSize = 10 * 1024 * 1024
func changeChunkSize(block int) {
	chunkSize = block * 1024 * 1024
}
var wg sync.WaitGroup
var threads = 3
var pool = make(chan struct{}, threads)
func changeThread(thread int) {
	threads = thread
	pool = make(chan struct{}, threads)
}
func getClient(file string, ctx context.Context, config *oauth2.Config) *http.Client {
	tok := &oauth2.Token{}  
	return config.Client(ctx, tok)  
}
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
	fmt.Printf("在浏览器中进入以下链接，然后输入授权码: \n%v\n", authURL)
	var code string
	if _, err := fmt.Scan(&code); err != nil {
		log.Fatalf("Unable to read authorization code %v", err)
	}
	tok, err := config.Exchange(oauth2.NoContext, code)
	if err != nil {
		log.Fatalf("Unable to retrieve token from web %v", err)
	}
	return tok
}
func GetURL() string {
	_, config := gdInit()
	authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
	return authURL
}
func tokenCacheFile() string {
	return filepath.Join("./", "drive-go-quickstart.json")
}
func tokenFromFile(c *oauth2.Config, file string, Thread int, BlockSize int, Language string, TimeOut int, BotKey string, UserID string) (*oauth2.Token, error) {
	f, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	ts := &httpLocal.Certificate{}
	err = json.NewDecoder(f).Decode(ts)  
	oauth2Token := ts.Other.(map[string]interface{})
	expiry, _ := time.Parse(time.RFC3339, oauth2Token["expiry"].(string))
	t := &oauth2.Token{
		AccessToken:  oauth2Token["access_token"].(string),
		TokenType:    oauth2Token["token_type"].(string),
		RefreshToken: oauth2Token["refresh_token"].(string),
		Expiry:       expiry,
	}
	defer f.Close()
	f, err = os.OpenFile(file, os.O_WRONLY|os.O_TRUNC, 0666)
	defer f.Close()
	updatedToken, err := c.TokenSource(context.TODO(), t).Token()
	data := httpLocal.Certificate{
		Drive:        "GoogleDrive",
		RefreshToken: ts.RefreshToken,
		ThreadNum:    Thread,
		BlockSize:    BlockSize,
		MainLand:     false,
		Language:     Language,
		TimeOut:      TimeOut,
		BotKey:       BotKey,
		UserID:       UserID,
		Other:        updatedToken,
	}
	err = json.NewEncoder(f).Encode(data)
	if err != nil {
		log.Fatalf("Unable to cache oauth token: %v", err)
	}
	changeThread(Thread)
	changeChunkSize(BlockSize)
	return updatedToken, err
}
func saveToken(file string, token *oauth2.Token, lang string) {
	f, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		log.Fatalf("Unable to cache oauth token: %v", err)
	}
	defer f.Close()
	data := httpLocal.Certificate{
		Drive:        "GoogleDrive",
		RefreshToken: token.RefreshToken,
		ThreadNum:    3,
		BlockSize:    10,
		MainLand:     false,
		Language:     lang,
		TimeOut:      60,
		BotKey:       "",
		UserID:       "",
		Other:        token,
	}
	json.NewEncoder(f).Encode(data)
}
func byte2Readable(bytes float64) string {
	const kb float64 = 1024
	const mb float64 = kb * 1024
	const gb float64 = mb * 1024
	var readable float64
	var unit string
	_bytes := bytes
	if _bytes >= gb {
		readable = _bytes / gb
		unit = "GB"
	} else if _bytes < gb && _bytes >= mb {
		readable = _bytes / mb
		unit = "MB"
	} else {
		readable = _bytes / kb
		unit = "KB"
	}
	return strconv.FormatFloat(readable, 'f', 2, 64) + " " + unit
}
func UploadAllFile(pathname string, folderIDList []string, srv *drive.Service, startTime int64, username string, sendMsg func() (func(text string), string, string, func(string, string, string) func(string)), locText func(text string) string) (func(string), error) {
	filePath := path.Base(pathname)
	temps, _botKey, iUserID, BotSend := sendMsg()
	var iSendMsg func(string)
	tip := "`" + filePath + "`" + locText("startUploadGoogleDrive")
	if _botKey != "" && iUserID != "" {
		iSendMsg = BotSend(_botKey, iUserID, tip)
	}
	temp := func(text string) {
		temps(text)
		if _botKey != "" && iUserID != "" {
			iSendMsg(text)
		}
	}
	temp(tip)
	rd, err := ioutil.ReadDir(pathname)
	if err != nil {
		_, fullName := filepath.Split(pathname)
		var tempFolderIDList []string
		if folderIDList == nil {
			tempFolderIDList = folderIDList
		}
		f, err := os.Open(fullName)
		if err != nil {
			log.Fatalf("error opening %q: %v", fullName, err)
		}
		defer f.Close()
		uploadFile(srv, pathname, fullName, tempFolderIDList, f, sendMsg, locText, username)
	}
	_, foldName := filepath.Split(pathname)
	var createFolder *drive.File
	if folderIDList == nil {
		createFolder, err = srv.Files.Create(&drive.File{Name: foldName, MimeType: "application/vnd.google-apps.folder"}).Do()
	} else {
		createFolder, err = srv.Files.Create(&drive.File{Name: foldName, Parents: folderIDList, MimeType: "application/vnd.google-apps.folder"}).Do()
	}
	if err != nil {
		log.Panicf("Unable to create folder: %v", err)
	}
	for _, fi := range rd {
		if fi.IsDir() {
			fullDir := pathname + "/" + fi.Name()
			var tempFolderIDList []string
			if folderIDList == nil {
				tempFolderIDList = folderIDList
			}
			tempFolderIDList = append(tempFolderIDList, createFolder.Id)
			_, err := UploadAllFile(fullDir, tempFolderIDList, srv, startTime, username, sendMsg, locText)
			if err != nil {
				log.Panic("read dir fail:", err)
				return nil, err
			}
		} else {
			fullName := pathname + "/" + fi.Name()
			var tempFolderIDList []string
			if folderIDList == nil {
				tempFolderIDList = folderIDList
			}
			tempFolderIDList = append(tempFolderIDList, createFolder.Id)
			f, err := os.Open(fullName)
			if err != nil {
				log.Fatalf("error opening %q: %v", fullName, err)
			}
			defer f.Close()
			uploadFile(srv, fullName, fi.Name(), tempFolderIDList, f, sendMsg, locText, username)
			if err != nil {
				log.Panicf("Unable to create file: %v", err)
			}
		}
	}
	wg.Wait()
	return temp, nil
}
func FileSizeFormat(bytes int64, forceBytes bool) string {
	if forceBytes {
		return fmt.Sprintf("%v B", bytes)
	}
	units := []string{"B", "KB", "MB", "GB", "TB", "PB"}
	var i int
	value := float64(bytes)
	for value > 1000 {
		value /= 1000
		i++
	}
	return fmt.Sprintf("%.1f %s", value, units[i])
}
func MeasureTransferRate() func(int64) string {
	start := time.Now()
	return func(bytes int64) string {
		seconds := int64(time.Now().Sub(start).Seconds())
		if seconds < 1 {
			return fmt.Sprintf("%s/s", FileSizeFormat(bytes, false))
		}
		bps := bytes / seconds
		return fmt.Sprintf("%s/s", FileSizeFormat(bps, false))
	}
}
func uploadFile(srv *drive.Service, filePath string, filename string, tempFolderIDList []string, f *os.File, sendMsg func() (func(text string), string, string, func(string, string, string) func(string)), locText func(text string) string, username string) {
	wg.Add(1)
	pool <- struct{}{}
	startTime := time.Now().Unix()
	go func() {
		defer wg.Done()
		defer func() {
			<-pool
		}()
		temps, _botKey, iUserID, botSend := sendMsg()
		var iSendMsg func(string)
		tip := "`" + filePath + "`" + locText("startToUpload1")
		if _botKey != "" && iUserID != "" {
			iSendMsg = botSend(_botKey, iUserID, tip)
		}
		temp := func(text string) {
			temps(text)
			if _botKey != "" && iUserID != "" {
				iSendMsg(text)
			}
		}
		fi, err := os.Stat(filePath)
		if err != nil {
			fi, err = os.Stat(filename)
			if err != nil {
				log.Panicln(err)
			}
		}
		getRate := MeasureTransferRate()
		size := fi.Size()
		showProgress := func(current, total int64) {
			temp(fmt.Sprintf(locText("googleDriveUploadTip1"), username, filePath, byte2Readable(float64(size)), byte2Readable(float64(current)), int(math.Ceil(float64(current)/float64(chunkSize))), int(math.Ceil(float64(size)/float64(chunkSize))), getRate(current), time.Now().Unix()-startTime))
		}
		_, err = srv.Files.Create(&drive.File{Name: filename, Parents: tempFolderIDList}).Media(f, googleapi.ChunkSize(chunkSize)).ProgressUpdater(showProgress).Do()
		if err != nil {
			log.Panicln(err)
		}
		defer temp("close")
	}()
}