SHARE
TWEET

Untitled

a guest Aug 28th, 2019 30 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package main
  2.  
  3. import (
  4.         "crypto/sha256"
  5.         "fmt"
  6.         "io"
  7.         "log"
  8.         "net/http"
  9.         "os"
  10.         "regexp"
  11.         "strings"
  12.  
  13.         "github.com/PuerkitoBio/goquery"
  14. )
  15.  
  16. type arch struct {
  17.         title     string
  18.         sha256sum string
  19. }
  20.  
  21. const repoURL = "https://repo.nordvpn.com/deb/nordvpn/debian/pool/main/"
  22.  
  23. var packageRegex = regexp.MustCompile(`^nordvpn_(.+)_(.+)\.deb$`)
  24.  
  25. func main() {
  26.  
  27.         // Download Goquery document
  28.         doc, err := downloadAsGoqueryDocument(repoURL)
  29.         if err != nil {
  30.                 log.Fatal(err)
  31.         }
  32.  
  33.         // Find last A element, so we can understand what is the latest version from it
  34.         el := doc.Find(`a[href$=".deb"][href^="nordvpn_"]`).Last()
  35.         if el == nil {
  36.                 log.Fatal("unable to read packages from the repo document")
  37.         }
  38.         packageTitle, _ := el.Attr("href")
  39.  
  40.         // Read version from that package name
  41.         regexExtractArray := packageRegex.FindStringSubmatch(packageTitle)
  42.         if len(regexExtractArray) != 3 {
  43.                 log.Fatal("regex is broken and needs to be fixed")
  44.         }
  45.         version := regexExtractArray[1]
  46.  
  47.         // Find all available architectures and create slice of 'arch'
  48.         architectures := findArchitectures(doc, version)
  49.  
  50.         // Fill sha256sum checksums for each 'arch'
  51.         fillChecksums(&architectures, &version)
  52.  
  53.         // Print PKGBUILD file content
  54.         printPKGBUILD(&architectures, &version)
  55.  
  56. }
  57.  
  58. func printPKGBUILD(architectures *[]arch, version *string) {
  59.  
  60.         // First we generate variables
  61.         var sourceLines, sha256sumLines string
  62.         archLine := "arch=("
  63.  
  64.         for _, architecture := range *architectures {
  65.                 switch architecture.title {
  66.                 case "i386":
  67.                         archLine += "'i686' "
  68.                         sourceLines += "source_i686=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  69.                         sha256sumLines += "sha256sums_i686=(\"" + architecture.sha256sum + "\")\n"
  70.                 case "amd64":
  71.                         archLine += "'x86_64' "
  72.                         sourceLines += "source_x86_64=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  73.                         sha256sumLines += "sha256sums_x86_64=(\"" + architecture.sha256sum + "\")\n"
  74.                 case "armhf":
  75.                         archLine += "'armv7h' "
  76.                         sourceLines += "source_armv7h=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  77.                         sha256sumLines += "sha256sums_armv7h=(\"" + architecture.sha256sum + "\")\n"
  78.                 case "armel":
  79.                         archLine += "'armv6h' "
  80.                         sourceLines += "source_armv6h=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  81.                         sha256sumLines += "sha256sums_armv6h=(\"" + architecture.sha256sum + "\")\n"
  82.                         archLine += "'arm' "
  83.                         sourceLines += "source_arm=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  84.                         sha256sumLines += "sha256sums_arm=(\"" + architecture.sha256sum + "\")\n"
  85.                 case "arm64":
  86.                         archLine += "'aarch64' "
  87.                         sourceLines += "source_aarch64=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  88.                         sha256sumLines += "sha256sums_aarch64=(\"" + architecture.sha256sum + "\")\n"
  89.                 default:
  90.                         archLine += "'" + architecture.title + "' "
  91.                         sourceLines += "source_" + architecture.title + "=(\"" + repoURL + "nordvpn_" + *version + "_" + architecture.title + ".deb\")\n"
  92.                         sha256sumLines += "sha256sums_" + architecture.title + "=(\"" + architecture.sha256sum + "\")\n"
  93.                 }
  94.         }
  95.  
  96.         archLine = archLine[:len(archLine)-1] + ")"
  97.         sourceLines = sourceLines[:len(sourceLines)-1]
  98.         sha256sumLines = sha256sumLines[:len(sha256sumLines)-1]
  99.  
  100.         // Now we print everything:
  101.  
  102.         fmt.Printf(`# Maintainer: metiis <aur at metiis dot com>
  103. # Maintainer: Julio Gutierrez <bubuntux at gmail dot com>
  104. # Maintainer: Martoko <mbastholm at gmail dot com>
  105.  
  106. pkgname=nordvpn-cli
  107. pkgver=%s
  108. pkgrel=1
  109. pkgdesc="Official NordVPN CLI for Linux"
  110. %s
  111. url="https://nordvpn.com/download/linux/"
  112. license=('custom')
  113. depends=('net-tools' 'libxslt' 'iptables' 'procps' 'iproute2')
  114. optdepends=('wireguard-tools: nordlynx support' 'wireguard-module: nordlynx support')
  115. provides=('nordvpn')
  116. conflicts=('openvpn-nordvpn')
  117. install=nordvpn-cli.install
  118. %s
  119. %s
  120.  
  121. package() {
  122.         bsdtar -O -xf *.deb data.tar.xz | bsdtar -C "${pkgdir}" -xJf -
  123.  
  124.         mv "${pkgdir}/usr/sbin/nordvpnd" "${pkgdir}/usr/bin"
  125.         rm -r "${pkgdir}/etc/init.d"
  126.         rm -r "${pkgdir}/usr/sbin"
  127. }
  128. `, strings.ReplaceAll(*version, "-", "_"), archLine, sourceLines, sha256sumLines)
  129. }
  130.  
  131. func fillChecksums(architectures *[]arch, version *string) {
  132.         for i := 0; i < len(*architectures); i++ {
  133.  
  134.                 // Construct titles/paths:
  135.                 fileName := "nordvpn_" + *version + "_" + (*architectures)[i].title + ".deb"
  136.                 filePath := "/tmp/" + fileName
  137.  
  138.                 // Download file to tmp
  139.                 err := downloadFile(filePath, repoURL+fileName)
  140.                 if err != nil {
  141.                         log.Fatal(err)
  142.                 }
  143.  
  144.                 // Calculate sha256sum
  145.                 f, err := os.Open(filePath)
  146.                 if err != nil {
  147.                         log.Fatal(err)
  148.                 }
  149.                 defer f.Close()
  150.  
  151.                 h := sha256.New()
  152.                 if _, err := io.Copy(h, f); err != nil {
  153.                         log.Fatal(err)
  154.                 }
  155.                 (*architectures)[i].sha256sum = fmt.Sprintf("%x", h.Sum(nil))
  156.  
  157.                 // Delete file from tmp
  158.                 err = os.Remove(filePath)
  159.                 if err != nil {
  160.                         log.Fatal(err)
  161.                 }
  162.         }
  163. }
  164.  
  165. func findArchitectures(doc *goquery.Document, version string) (availablePackages []arch) {
  166.         doc.Find(`a[href$=".deb"][href^="nordvpn_` + version + `"]`).Each(func(i int, s *goquery.Selection) {
  167.                 title, _ := s.Attr("href")
  168.                 arr := packageRegex.FindStringSubmatch(title)
  169.                 if len(arr) != 3 {
  170.                         log.Fatal("regex is broken and needs to be fixed")
  171.                 }
  172.                 availablePackages = append(availablePackages, arch{title: arr[2]})
  173.         })
  174.         return
  175. }
  176.  
  177. func downloadAsGoqueryDocument(url string) (*goquery.Document, error) {
  178.         res, err := http.Get(url)
  179.         if err != nil {
  180.                 return nil, err
  181.         }
  182.         defer res.Body.Close()
  183.         if res.StatusCode != 200 {
  184.                 return nil, fmt.Errorf("status code error: %d %s", res.StatusCode, res.Status)
  185.         }
  186.         return goquery.NewDocumentFromReader(res.Body)
  187. }
  188.  
  189. func downloadFile(filepath string, url string) error {
  190.  
  191.         // Get the data
  192.         resp, err := http.Get(url)
  193.         if err != nil {
  194.                 return err
  195.         }
  196.         defer resp.Body.Close()
  197.  
  198.         // Create the file
  199.         out, err := os.Create(filepath)
  200.         if err != nil {
  201.                 return err
  202.         }
  203.         defer out.Close()
  204.  
  205.         // Write the body to file
  206.         _, err = io.Copy(out, resp.Body)
  207.         return err
  208. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top