func (api *API) renterClearDownloadsHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	var afterTime time.Time
	beforeTime := types.EndOfTime
	beforeStr, afterStr := req.FormValue("before"), req.FormValue("after")
	if beforeStr != "" {
		beforeInt, err := strconv.ParseInt(beforeStr, 10, 64)
		if err != nil {
			WriteError(w, Error{"parsing integer value for parameter `before` failed: " + err.Error()}, http.StatusBadRequest)
			return
		}
		beforeTime = time.Unix(0, beforeInt)
	}
	if afterStr != "" {
		afterInt, err := strconv.ParseInt(afterStr, 10, 64)
		if err != nil {
			WriteError(w, Error{"parsing integer value for parameter `after` failed: " + err.Error()}, http.StatusBadRequest)
			return
		}
		afterTime = time.Unix(0, afterInt)
	}
	err := api.renter.ClearDownloadHistory(afterTime, beforeTime)
	if err != nil {
		WriteError(w, Error{err.Error()}, http.StatusBadRequest)
		return
	}
	WriteSuccess(w)
}
renterClearDownloadsHandler handles the API call to request to clear the download queue.
package api
import (
	"fmt"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter"
	"github.com/NebulousLabs/Sia/types"
	"github.com/julienschmidt/httprouter"
)
var (
	recommendedHosts = build.Select(build.Var{
		Standard: uint64(50),
		Dev:      uint64(2),
		Testing:  uint64(1),
	}).(uint64)
	requiredHosts = build.Select(build.Var{
		Standard: uint64(20),
		Dev:      uint64(1),
		Testing:  uint64(1),
	}).(uint64)
	requiredParityPieces = build.Select(build.Var{
		Standard: int(12),
		Dev:      int(0),
		Testing:  int(0),
	}).(int)
	requiredRedundancy = build.Select(build.Var{
		Standard: float64(2),
		Dev:      float64(1),
		Testing:  float64(1),
	}).(float64)
	requiredRenewWindow = build.Select(build.Var{
		Standard: types.BlockHeight(288),
		Dev:      types.BlockHeight(1),
		Testing:  types.BlockHeight(1),
	}).(types.BlockHeight)
)
type (
	RenterGET struct {
		Settings         modules.RenterSettings     `json:"settings"`
		FinancialMetrics modules.ContractorSpending `json:"financialmetrics"`
		CurrentPeriod    types.BlockHeight          `json:"currentperiod"`
	}
	RenterContract struct {
		DownloadSpending types.Currency `json:"downloadspending"`
		EndHeight types.BlockHeight `json:"endheight"`
		Fees types.Currency `json:"fees"`
		HostPublicKey types.SiaPublicKey `json:"hostpublickey"`
		ID types.FileContractID `json:"id"`
		LastTransaction types.Transaction `json:"lasttransaction"`
		NetAddress modules.NetAddress `json:"netaddress"`
		RenterFunds types.Currency `json:"renterfunds"`
		Size uint64 `json:"size"`
		StartHeight types.BlockHeight `json:"startheight"`
		StorageSpending types.Currency `json:"storagespending"`
		StorageSpendingDeprecated types.Currency `json:"StorageSpending"`
		TotalCost types.Currency `json:"totalcost"`
		UploadSpending types.Currency `json:"uploadspending"`
		GoodForUpload bool `json:"goodforupload"`
		GoodForRenew bool `json:"goodforrenew"`
	}
	RenterContracts struct {
		Contracts         []RenterContract `json:"contracts"`
		ActiveContracts   []RenterContract `json:"activecontracts"`
		InactiveContracts []RenterContract `json:"inactivecontracts"`
		ExpiredContracts  []RenterContract `json:"expiredcontracts"`
	}
	RenterDownloadQueue struct {
		Downloads []DownloadInfo `json:"downloads"`
	}
	RenterFile struct {
		File modules.FileInfo `json:"file"`
	}
	RenterFiles struct {
		Files []modules.FileInfo `json:"files"`
	}
	RenterLoad struct {
		FilesAdded []string `json:"filesadded"`
	}
	RenterPricesGET struct {
		modules.RenterPriceEstimation
	}
	RenterShareASCII struct {
		ASCIIsia string `json:"asciisia"`
	}
	DownloadInfo struct {
		Destination     string `json:"destination"`      
		DestinationType string `json:"destinationtype"`  
		Filesize        uint64 `json:"filesize"`         
		Length          uint64 `json:"length"`           
		Offset          uint64 `json:"offset"`           
		SiaPath         string `json:"siapath"`          
		Completed            bool      `json:"completed"`             
		EndTime              time.Time `json:"endtime"`               
		Error                string    `json:"error"`                 
		Received             uint64    `json:"received"`              
		StartTime            time.Time `json:"starttime"`             
		StartTimeUnix        int64     `json:"starttimeunix"`         
		TotalDataTransferred uint64    `json:"totaldatatransferred"`  
	}
)
func (api *API) renterHandlerGET(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	settings := api.renter.Settings()
	periodStart := api.renter.CurrentPeriod()
	WriteJSON(w, RenterGET{
		Settings:         settings,
		FinancialMetrics: api.renter.PeriodSpending(),
		CurrentPeriod:    periodStart,
	})
}
func (api *API) renterHandlerPOST(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	settings := api.renter.Settings()
	if f := req.FormValue("funds"); f != "" {
		funds, ok := scanAmount(f)
		if !ok {
			WriteError(w, Error{"unable to parse funds"}, http.StatusBadRequest)
			return
		}
		settings.Allowance.Funds = funds
	}
	if h := req.FormValue("hosts"); h != "" {
		var hosts uint64
		if _, err := fmt.Sscan(h, &hosts); err != nil {
			WriteError(w, Error{"unable to parse hosts: " + err.Error()}, http.StatusBadRequest)
			return
		} else if hosts != 0 && hosts < requiredHosts {
			WriteError(w, Error{fmt.Sprintf("insufficient number of hosts, need at least %v but have %v", recommendedHosts, hosts)}, http.StatusBadRequest)
		} else {
			settings.Allowance.Hosts = hosts
		}
	} else if settings.Allowance.Hosts == 0 {
		settings.Allowance.Hosts = recommendedHosts
	}
	if p := req.FormValue("period"); p != "" {
		var period types.BlockHeight
		if _, err := fmt.Sscan(p, &period); err != nil {
			WriteError(w, Error{"unable to parse period: " + err.Error()}, http.StatusBadRequest)
			return
		}
		settings.Allowance.Period = types.BlockHeight(period)
	} else if settings.Allowance.Period == 0 {
		WriteError(w, Error{"period needs to be set if it hasn't been set before"}, http.StatusBadRequest)
		return
	}
	if rw := req.FormValue("renewwindow"); rw != "" {
		var renewWindow types.BlockHeight
		if _, err := fmt.Sscan(rw, &renewWindow); err != nil {
			WriteError(w, Error{"unable to parse renewwindow: " + err.Error()}, http.StatusBadRequest)
			return
		} else if renewWindow != 0 && types.BlockHeight(renewWindow) < requiredRenewWindow {
			WriteError(w, Error{fmt.Sprintf("renew window is too small, must be at least %v blocks but have %v blocks", requiredRenewWindow, renewWindow)}, http.StatusBadRequest)
			return
		} else {
			settings.Allowance.RenewWindow = types.BlockHeight(renewWindow)
		}
	} else if settings.Allowance.RenewWindow == 0 {
		settings.Allowance.RenewWindow = settings.Allowance.Period / 2
	}
	if d := req.FormValue("maxdownloadspeed"); d != "" {
		var downloadSpeed int64
		if _, err := fmt.Sscan(d, &downloadSpeed); err != nil {
			WriteError(w, Error{"unable to parse downloadspeed: " + err.Error()}, http.StatusBadRequest)
			return
		}
		settings.MaxDownloadSpeed = downloadSpeed
	}
	if u := req.FormValue("maxuploadspeed"); u != "" {
		var uploadSpeed int64
		if _, err := fmt.Sscan(u, &uploadSpeed); err != nil {
			WriteError(w, Error{"unable to parse uploadspeed: " + err.Error()}, http.StatusBadRequest)
			return
		}
		settings.MaxUploadSpeed = uploadSpeed
	}
	if dcs := req.FormValue("streamcachesize"); dcs != "" {
		var streamCacheSize uint64
		if _, err := fmt.Sscan(dcs, &streamCacheSize); err != nil {
			WriteError(w, Error{"unable to parse streamcachesize: " + err.Error()}, http.StatusBadRequest)
			return
		}
		settings.StreamCacheSize = streamCacheSize
	}
	err := api.renter.SetSettings(settings)
	if err != nil {
		WriteError(w, Error{err.Error()}, http.StatusBadRequest)
		return
	}
	WriteSuccess(w)
}
func (api *API) renterContractsHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	inactive, err := scanBool(req.FormValue("inactive"))
	if err != nil {
		return
	}
	expired, err := scanBool(req.FormValue("expired"))
	if err != nil {
		return
	}
	blockHeight := api.cs.Height()
	contracts := []RenterContract{}
	activeContracts := []RenterContract{}
	inactiveContracts := []RenterContract{}
	expiredContracts := []RenterContract{}
	for _, c := range api.renter.Contracts() {
		var size uint64
		if len(c.Transaction.FileContractRevisions) != 0 {
			size = c.Transaction.FileContractRevisions[0].NewFileSize
		}
		var netAddress modules.NetAddress
		hdbe, exists := api.renter.Host(c.HostPublicKey)
		if exists {
			netAddress = hdbe.NetAddress
		}
		var goodForUpload bool
		var goodForRenew bool
		if utility, ok := api.renter.ContractUtility(c.HostPublicKey); ok {
			goodForUpload = utility.GoodForUpload
			goodForRenew = utility.GoodForRenew
		}
		contract := RenterContract{
			DownloadSpending:          c.DownloadSpending,
			EndHeight:                 c.EndHeight,
			Fees:                      c.TxnFee.Add(c.SiafundFee).Add(c.ContractFee),
			GoodForUpload:             goodForUpload,
			GoodForRenew:              goodForRenew,
			HostPublicKey:             c.HostPublicKey,
			ID:                        c.ID,
			LastTransaction:           c.Transaction,
			NetAddress:                netAddress,
			RenterFunds:               c.RenterFunds,
			Size:                      size,
			StartHeight:               c.StartHeight,
			StorageSpending:           c.StorageSpending,
			StorageSpendingDeprecated: c.StorageSpending,
			TotalCost:                 c.TotalCost,
			UploadSpending:            c.UploadSpending,
		}
		if goodForRenew {
			activeContracts = append(activeContracts, contract)
		} else if inactive && !goodForRenew {
			inactiveContracts = append(inactiveContracts, contract)
		}
		contracts = append(contracts, contract)
	}
	if expired || inactive {
		for _, c := range api.renter.OldContracts() {
			var size uint64
			if len(c.Transaction.FileContractRevisions) != 0 {
				size = c.Transaction.FileContractRevisions[0].NewFileSize
			}
			var netAddress modules.NetAddress
			hdbe, exists := api.renter.Host(c.HostPublicKey)
			if exists {
				netAddress = hdbe.NetAddress
			}
			var goodForUpload bool
			var goodForRenew bool
			if utility, ok := api.renter.ContractUtility(c.HostPublicKey); ok {
				goodForUpload = utility.GoodForUpload
				goodForRenew = utility.GoodForRenew
			}
			contract := RenterContract{
				DownloadSpending:          c.DownloadSpending,
				EndHeight:                 c.EndHeight,
				Fees:                      c.TxnFee.Add(c.SiafundFee).Add(c.ContractFee),
				GoodForUpload:             goodForUpload,
				GoodForRenew:              goodForRenew,
				HostPublicKey:             c.HostPublicKey,
				ID:                        c.ID,
				LastTransaction:           c.Transaction,
				NetAddress:                netAddress,
				RenterFunds:               c.RenterFunds,
				Size:                      size,
				StartHeight:               c.StartHeight,
				StorageSpending:           c.StorageSpending,
				StorageSpendingDeprecated: c.StorageSpending,
				TotalCost:                 c.TotalCost,
				UploadSpending:            c.UploadSpending,
			}
			if expired && c.EndHeight < blockHeight {
				expiredContracts = append(expiredContracts, contract)
			} else if inactive && c.EndHeight >= blockHeight {
				inactiveContracts = append(inactiveContracts, contract)
			}
		}
	}
	WriteJSON(w, RenterContracts{
		Contracts:         contracts,
		ActiveContracts:   activeContracts,
		InactiveContracts: inactiveContracts,
		ExpiredContracts:  expiredContracts,
	})
}