gitee.com/mysnapcore/mysnapd@v0.1.0/cmd/snap/cmd_buy.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package main
    21  
    22  import (
    23  	"fmt"
    24  	"strings"
    25  
    26  	"github.com/jessevdk/go-flags"
    27  
    28  	"gitee.com/mysnapcore/mysnapd/client"
    29  	"gitee.com/mysnapcore/mysnapd/i18n"
    30  )
    31  
    32  var shortBuyHelp = i18n.G("Buy a snap")
    33  var longBuyHelp = i18n.G(`
    34  The buy command buys a snap from the store.
    35  `)
    36  
    37  type cmdBuy struct {
    38  	clientMixin
    39  	Positional struct {
    40  		SnapName remoteSnapName
    41  	} `positional-args:"yes" required:"yes"`
    42  }
    43  
    44  func init() {
    45  	cmd := addCommand("buy", shortBuyHelp, longBuyHelp, func() flags.Commander {
    46  		return &cmdBuy{}
    47  	}, map[string]string{}, []argDesc{{
    48  		name: "<snap>",
    49  		// TRANSLATORS: This should not start with a lowercase letter.
    50  		desc: i18n.G("Snap name"),
    51  	}})
    52  	cmd.hidden = true
    53  }
    54  
    55  func (x *cmdBuy) Execute(args []string) error {
    56  	if len(args) > 0 {
    57  		return ErrExtraArgs
    58  	}
    59  
    60  	return buySnap(x.client, string(x.Positional.SnapName))
    61  }
    62  
    63  func buySnap(cli *client.Client, snapName string) error {
    64  	user := cli.LoggedInUser()
    65  	if user == nil {
    66  		return fmt.Errorf(i18n.G("You need to be logged in to purchase software. Please run 'snap login' and try again."))
    67  	}
    68  
    69  	if strings.ContainsAny(snapName, ":*") {
    70  		return fmt.Errorf(i18n.G("cannot buy snap: invalid characters in name"))
    71  	}
    72  
    73  	snap, resultInfo, err := cli.FindOne(snapName)
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	opts := &client.BuyOptions{
    79  		SnapID:   snap.ID,
    80  		Currency: resultInfo.SuggestedCurrency,
    81  	}
    82  
    83  	opts.Price, opts.Currency, err = getPrice(snap.Prices, opts.Currency)
    84  	if err != nil {
    85  		return fmt.Errorf(i18n.G("cannot buy snap: %v"), err)
    86  	}
    87  
    88  	if snap.Status == "available" {
    89  		return fmt.Errorf(i18n.G("cannot buy snap: it has already been bought"))
    90  	}
    91  
    92  	err = cli.ReadyToBuy()
    93  	if err != nil {
    94  		if e, ok := err.(*client.Error); ok {
    95  			switch e.Kind {
    96  			case client.ErrorKindNoPaymentMethods:
    97  				return fmt.Errorf(i18n.G(`You need to have a payment method associated with your account in order to buy a snap, please visit https://my.ubuntu.com/payment/edit to add one.
    98  
    99  Once you’ve added your payment details, you just need to run 'snap buy %s' again.`), snap.Name)
   100  			case client.ErrorKindTermsNotAccepted:
   101  				return fmt.Errorf(i18n.G(`In order to buy %q, you need to agree to the latest terms and conditions. Please visit https://my.ubuntu.com/payment/edit to do this.
   102  
   103  Once completed, return here and run 'snap buy %s' again.`), snap.Name, snap.Name)
   104  			}
   105  		}
   106  		return err
   107  	}
   108  
   109  	// TRANSLATORS: %q, %q and %s are the snap name, developer, and price. Please wrap the translation at 80 characters.
   110  	fmt.Fprintf(Stdout, i18n.G(`Please re-enter your Ubuntu One password to purchase %q from %q
   111  for %s. Press ctrl-c to cancel.`), snap.Name, snap.Publisher.Username, formatPrice(opts.Price, opts.Currency))
   112  	fmt.Fprint(Stdout, "\n")
   113  
   114  	err = requestLogin(cli, user.Email)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	_, err = cli.Buy(opts)
   120  	if err != nil {
   121  		if e, ok := err.(*client.Error); ok {
   122  			switch e.Kind {
   123  			case client.ErrorKindPaymentDeclined:
   124  				return fmt.Errorf(i18n.G(`Sorry, your payment method has been declined by the issuer. Please review your
   125  payment details at https://my.ubuntu.com/payment/edit and try again.`))
   126  			}
   127  		}
   128  		return err
   129  	}
   130  
   131  	// TRANSLATORS: %q and %s are the same snap name. Please wrap the translation at 80 characters.
   132  	fmt.Fprintf(Stdout, i18n.G(`Thanks for purchasing %q. You may now install it on any of your devices
   133  with 'snap install %s'.`), snapName, snapName)
   134  	fmt.Fprint(Stdout, "\n")
   135  
   136  	return nil
   137  }