You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: webapi.go
    path of file: ./repos/rclone/backend/seafile
    
    the code of the file until where you have to start completion: package seafile

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
	"strings"

	"github.com/rclone/rclone/backend/seafile/api"
	"github.com/rclone/rclone/fs"
	"github.com/rclone/rclone/lib/readers"
	"github.com/rclone/rclone/lib/rest"
)

// Start of the API URLs
const (
	APIv20 = "api2/repos/"
	APIv21 = "api/v2.1/repos/"
)

// Errors specific to seafile fs
var (
	ErrorInternalDuringUpload = errors.New("internal server error during file upload")
)

// ==================== Seafile API ====================

func (f *Fs) getAuthorizationToken(ctx context.Context) (string, error) {
	return getAuthorizationToken(ctx, f.srv, f.opt.User, f.opt.Password, "")
}

// getAuthorizationToken can be called outside of an fs (during configuration of the remote to get the authentication token)
// it's doing a single call (no pacer involved)
func getAuthorizationToken(ctx context.Context, srv *rest.Client, user, password, oneTimeCode string) (string, error) {
	// API Documentation
	// https://download.seafile.com/published/web-api/home.md#user-content-Quick%20Start
	opts := rest.Opts{
		Method:       "POST",
		Path:         "api2/auth-token/",
		ExtraHeaders: map[string]string{"Authorization": ""}, // unset the Authorization for this request
		IgnoreStatus: true,                                   
    
func (f *Fs) getDirectoryEntriesAPIv21(ctx context.Context, libraryID, dirPath string, recursive bool) ([]api.DirEntry, error) {
	// API Documentation
	// https://download.seafile.com/published/web-api/v2.1/directories.md#user-content-List%20Items%20in%20Directory
	// This is using the undocumented version 2.1 of the API (so we can use the recursive option which is not available in the version 2)
	if libraryID == "" {
		return nil, errors.New("cannot list files without a library")
	}
	dirPath = path.Join("/", dirPath)

	recursiveFlag := "0"
	if recursive {
		recursiveFlag = "1"
	}
	opts := rest.Opts{
		Method: "GET",
		Path:   APIv21 + libraryID + "/dir/",
		Parameters: url.Values{
			"recursive": {recursiveFlag},
			"p":         {f.opt.Enc.FromStandardPath(dirPath)},
		},
	}
	result := &api.DirEntries{}
	var resp *http.Response
	var err error
	err = f.pacer.Call(func() (bool, error) {
		resp, err = f.srv.CallJSON(ctx, &opts, nil, &result)
		return f.shouldRetry(ctx, resp, err)
	})
	if err != nil {
		if resp != nil {
			if resp.StatusCode == 401 || resp.StatusCode == 403 {
				return nil, fs.ErrorPermissionDenied
			}
			if resp.StatusCode == 404 {
				return nil, fs.ErrorDirNotFound
			}
			if resp.StatusCode == 440 {
				// Encrypted library and password not provided
				return nil, fs.ErrorPermissionDenied
			}
		}
		return nil, fmt.Errorf("failed to get directory contents: %w", err)
	}

	// Clean up encoded names
	for index, fileInfo := range result.Entries {
		fileInfo.Name = f.opt.Enc.ToStandardName(fileInfo.Name)
		fileInfo.Path = f.opt.Enc.ToStandardPath(fileInfo.Path)
		result.Entries[index] = fileInfo
	}
	return result.Entries, nil
}