{- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -} module Main ( main ) where import Control.Exception (Exception(..), handle) import Data.Char (isNumber) import Control.Monad.Catch (MonadThrow(..)) import Control.Monad.IO.Class (MonadIO(..)) import qualified Data.Map as Map import Options.Applicative (execParser) import SlackBuilder.CommandLine import SlackBuilder.Config import SlackBuilder.Trans import SlackBuilder.LatestVersionCheck import SlackBuilder.Update import qualified Toml import Data.Text (Text) import qualified Data.Text as Text import Control.Monad.Trans.Reader (ReaderT(..)) import SlackBuilder.Package (PackageDescription(..)) import qualified SlackBuilder.Package as Package import Text.URI.QQ (uri) import Data.Foldable (for_, find) import GHC.Records (HasField(..)) import System.Process (CmdSpec(..)) import System.Console.ANSI ( setSGR , SGR(..) , ColorIntensity(..) , Color(..) , ConsoleLayer(..) ) autoUpdatable :: [PackageDescription] autoUpdatable = [ PackageDescription { latest = let ghArguments = PackageOwner{ owner = "universal-ctags", name = "ctags" } template = Package.DownloadTemplate "https://github.com/universal-ctags/ctags/archive/{version}/ctags-{version}.tar.gz" in Package.Updater { detectLatest = latestGitHub ghArguments "(v)\\." , getVersion = reuploadWithTemplate template [] , is64 = False } , name = "universal-ctags" , downloaders = mempty } , PackageDescription { latest = let packagistArguments = PackageOwner{ owner = "composer", name = "composer" } template = Package.DownloadTemplate "https://getcomposer.org/download/{version}/composer.phar" in Package.Updater { detectLatest = latestPackagist packagistArguments , getVersion = downloadWithTemplate template , is64 = False } , name = "composer" , downloaders = mempty } , PackageDescription { latest = let ghArguments = PackageOwner { owner = "jitsi" , name = "jitsi-meet-electron" } template = Package.DownloadTemplate "https://github.com/jitsi/jitsi-meet-electron/releases/download/v{version}/jitsi-meet-x86_64.AppImage" in Package.Updater { detectLatest = latestGitHub ghArguments "(v)*" , getVersion = downloadWithTemplate template , is64 = True } , name = "jitsi-meet-desktop" , downloaders = mempty } , PackageDescription { latest = let ghArguments = PackageOwner { owner = "php" , name = "php-src" } template = Package.DownloadTemplate "https://www.php.net/distributions/php-{version}.tar.xz" in Package.Updater { detectLatest = latestGitHub ghArguments "(php-)8.2.\\d" , getVersion = downloadWithTemplate template , is64 = False } , name = "php82" , downloaders = mempty } , PackageDescription { latest = let ghArguments = PackageOwner { owner = "kovidgoyal" , name = "kitty" } template = Package.DownloadTemplate "https://github.com/kovidgoyal/kitty/releases/download/v{version}/kitty-{version}.tar.xz" in Package.Updater { detectLatest = latestGitHub ghArguments "(v)\\." , getVersion = reuploadWithTemplate template [RawCommand "go" ["mod", "vendor"]] , is64 = False } , name = "kitty" , downloaders = mempty } , PackageDescription { latest = let ghArguments = PackageOwner { owner = "rdiff-backup" , name = "rdiff-backup" } template = Package.DownloadTemplate "https://github.com/rdiff-backup/rdiff-backup/releases/download/v{version}/rdiff-backup-{version}.tar.gz" in Package.Updater { detectLatest = latestGitHub ghArguments "(v)\\." , getVersion = reuploadWithTemplate template [] , is64 = False } , name = "rdiff-backup" , downloaders = mempty } , PackageDescription { latest = let needle = "Linux—" textArguments = TextArguments { textURL = "https://help.webex.com/en-us/article/mqkve8/Webex-App-%7C-Release-notes" , versionPicker = Text.takeWhile (liftA2 (||) (== '.') isNumber) . Text.drop (Text.length needle) . snd . Text.breakOn needle } template = Package.DownloadTemplate "https://binaries.webex.com/WebexDesktop-Ubuntu-Official-Package/Webex.deb" in Package.Updater { detectLatest = latestText textArguments , getVersion = downloadWithTemplate template , is64 = True } , name = "webex" , downloaders = mempty } , PackageDescription { latest = let ghArguments = PackageOwner { owner = "librsync" , name = "librsync" } template = Package.DownloadTemplate "https://github.com/librsync/librsync/archive/v{version}/librsync-{version}.tar.gz" in Package.Updater { detectLatest = latestGitHub ghArguments "(v)\\." , getVersion = reuploadWithTemplate template [] , is64 = True } , name = "librsync" , downloaders = mempty } , PackageDescription { latest = let textArguments = TextArguments { textURL = "https://downloads.dlang.org/releases/LATEST" , versionPicker = Text.strip } template = Package.DownloadTemplate "https://downloads.dlang.org/releases/2.x/{version}/dmd.{version}.linux.tar.xz" in Package.Updater { detectLatest = latestText textArguments , getVersion = downloadWithTemplate template , is64 = False } , name = "dmd" , downloaders = mempty } , PackageDescription { latest = let textArguments = TextArguments { textURL = "https://downloads.dlang.org/releases/LATEST" , versionPicker = Text.strip } template = Package.DownloadTemplate "https://codeload.github.com/dlang/tools/tar.gz/v{version}" in Package.Updater { detectLatest = latestText textArguments , getVersion = reuploadWithTemplate template [] , is64 = False } , name = "d-tools" , downloaders = let dubArguments = PackageOwner{ owner = "dlang", name = "dub" } dscannerArguments = PackageOwner{ owner = "dlang-community", name = "D-Scanner" } dcdArguments = PackageOwner{ owner = "dlang-community", name = "DCD" } latestDub = Package.Updater { detectLatest = latestGitHub dubArguments "(v)\\." , getVersion = reuploadWithTemplate dubTemplate [] , is64 = False } latestDscanner = Package.Updater { detectLatest = latestGitHub dscannerArguments "(v)\\." , getVersion = cloneFromGit dscannerURI "v" , is64 = False } dcdURI = [uri|https://github.com/dlang-community/DCD.git|] latestDcd = Package.Updater { detectLatest = latestGitHub dcdArguments "(v)\\." , getVersion = cloneFromGit dcdURI "v" , is64 = False } dubTemplate = Package.DownloadTemplate "https://codeload.github.com/dlang/dub/tar.gz/v{version}" dscannerURI = [uri|https://github.com/dlang-community/D-Scanner.git|] in Map.fromList [ ("DUB", latestDub) , ("DSCANNER", latestDscanner) , ("DCD", latestDcd) ] } , PackageDescription { latest = let ghArguments = PackageOwner { owner = "simd-everywhere" , name = "simde" } template = Package.DownloadTemplate "https://github.com/simd-everywhere/simde/releases/download/v{version}/simde-amalgamated-{version}.tar.xz" in Package.Updater { detectLatest = latestGitHub ghArguments "(v)\\." , getVersion = downloadWithTemplate template , is64 = False } , name = "simde" , downloaders = mempty } ] up2Date :: Maybe Text -> SlackBuilderT () up2Date = \case Nothing -> for_ autoUpdatable go Just packageName | Just foundPackage <- find ((packageName ==) . getField @"name") autoUpdatable -> go foundPackage | otherwise -> throwM $ UpdaterNotFound packageName where go package = getAndLogLatest package >>= mapM_ updatePackageIfRequired >> liftIO (putStrLn "") check :: SlackBuilderT () check = for_ autoUpdatable go where go package = getAndLogLatest package >>= mapM_ checkUpdateAvailability >> liftIO (putStrLn "") main :: IO () main = do programCommand <- execParser slackBuilderParser settings <- Toml.decodeFile settingsCodec "config/config.toml" handle handleException $ flip runReaderT settings $ runSlackBuilderT $ executeCommand programCommand where handleException :: SlackBuilderException -> IO () handleException slackBuilderException = setSGR [SetColor Foreground Dull Red] >> putStrLn (displayException slackBuilderException) >> setSGR [Reset] executeCommand = \case CheckCommand -> check Up2DateCommand packageName -> up2Date packageName