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: plugin_install.go
    path of file: ./repos/mattermost/server/channels/app
    
    the code of the file until where you have to start completion: // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

// ### Plugin Bundles
//
// A plugin bundle consists of a server and/or webapp component designed to extend the
// functionality of the server. Bundles are first extracted to the configured local directory
// (PluginSettings.Directory), with any webapp component additionally copied to the configured
// local client directory (PluginSettings.ClientDirectory) to be loaded alongside the webap
    
func extractPlugin(bundle io.ReadSeeker, extractDir string) (*model.Manifest, string, *model.AppError) {
	bundle.Seek(0, 0)
	if err := extractTarGz(bundle, extractDir); err != nil {
		return nil, "", model.NewAppError("extractPlugin", "app.plugin.extract.app_error", nil, "", http.StatusBadRequest).Wrap(err)
	}

	dir, err := os.ReadDir(extractDir)
	if err != nil {
		return nil, "", model.NewAppError("extractPlugin", "app.plugin.filesystem.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
	}

	// If the root of the plugin bundle consists of exactly one directory, assume the plugin
	// is contained therein. Otherwise the root directory is expected to contain the plugin.
	if len(dir) == 1 && dir[0].IsDir() {
		extractDir = filepath.Join(extractDir, dir[0].Name())
	}

	manifest, _, err := model.FindManifest(extractDir)
	if err != nil {
		return nil, "", model.NewAppError("extractPlugin", "app.plugin.manifest.app_error", nil, "", http.StatusBadRequest).Wrap(err)
	}

	if !model.IsValidPluginId(manifest.Id) {
		return nil, "", model.NewAppError("extractPlugin", "app.plugin.invalid_id.app_error", map[string]any{"Min": model.MinIdLength, "Max": model.MaxIdLength, "Regex": model.ValidIdRegex}, "", http.StatusBadRequest)
	}

	return manifest, extractDir, nil
}