func (o *Oauth) refreshTokenFunction() (error, time.Duration) {
	form := url.Values{}
	form.Set("grant_type", "refresh_token")
	form.Set("refresh_token", o.refreshToken)
	req, _ := http.NewRequest("POST", "https://www.reddit.com/api/v1/access_token", strings.NewReader(form.Encode()))
	req.Header.Set("User-Agent", UserAgent)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.SetBasicAuth(o.clientId, o.clientSecret)
	resp, err := config.GlobalHttpClient.Do(req)
	if err != nil {
		return err, 0
	}
	var body tokenRequestResponse
	err = json.NewDecoder(resp.Body).Decode(&body)
	_ = resp.Body.Close()
	if err != nil {
		return err, 0
	}
	if resp.StatusCode != http.StatusOK {
		return errors.New("status code is not 200. It is " + resp.Status), 0
	}
	return nil, time.Duration(body.ExpiresIn) * time.Second
}
refreshTokenFunction refreshes the token from reddit servers
package reddit
import (
	"encoding/json"
	"errors"
	"github.com/HirbodBehnam/RedditDownloaderBot/config"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"sync"
	"time"
)
const UserAgent = "TelegramBot:Reddit-Downloader-Bot:" + config.Version + " (by /u/HirbodBehnam)"
const PostApiPoint = "https://api.reddit.com/api/info/?id=t3_"
const CommentApiPoint = "https://api.reddit.com/api/info/?id=t1_"
const encodedGrantType = "grant_type=client_credentials&duration=permanent"
var RateLimitError = errors.New("rate limit reached")
type Oauth struct {
	rateLimit time.Time
	clientId string
	clientSecret string
	authorizationHeader string
	refreshToken string
	rateLimitMutex sync.RWMutex
}
type tokenRequestResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"`
}
func NewRedditOauth(clientId, clientSecret string) (*Oauth, error) {
	redditOauth := &Oauth{
		clientId:     clientId,
		clientSecret: clientSecret,
	}
	err, nextRefresh := redditOauth.createToken()
	if err != nil {
		return nil, err
	}
	go redditOauth.tokenRefresh(nextRefresh)
	return redditOauth, nil
}
func (o *Oauth) tokenRefresh(nextRefresh time.Duration) {
	for {
		time.Sleep(nextRefresh - time.Minute)
		err, nextRefreshCandidate := o.refreshTokenFunction()
		if err != nil {
			log.Printf("cannot refresh token: %s", err.Error())
			nextRefresh = time.Minute
		} else {
			nextRefresh = nextRefreshCandidate
		}
	}
}
func (o *Oauth) createToken() (error, time.Duration) {
	req, _ := http.NewRequest("POST", "https://www.reddit.com/api/v1/access_token", strings.NewReader(encodedGrantType))
	req.Header.Set("User-Agent", UserAgent)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.SetBasicAuth(o.clientId, o.clientSecret)
	resp, err := config.GlobalHttpClient.Do(req)
	if err != nil {
		return err, 0
	}
	var body tokenRequestResponse
	err = json.NewDecoder(resp.Body).Decode(&body)
	_ = resp.Body.Close()
	if err != nil {
		return err, 0
	}
	if resp.StatusCode != http.StatusOK {
		return errors.New("status code is not 200. It is " + resp.Status), 0
	}
	o.authorizationHeader = "bearer: " + body.AccessToken
	o.refreshToken = body.RefreshToken
	return nil, time.Duration(body.ExpiresIn) * time.Second
}