cpod

Yet another cron-friendly podcatcher

git clone https://git.8pit.net/cpod.git

  1// Copyright (C) 2013-2015 Sören Tempel
  2//
  3// This program is free software: you can redistribute it and/or modify
  4// it under the terms of the GNU General Public License as published by
  5// the Free Software Foundation, either version 3 of the License, or
  6// (at your option) any later version.
  7//
  8// This program is distributed in the hope that it will be useful,
  9// but WITHOUT ANY WARRANTY; without even the implied warranty of
 10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 11// GNU General Public License for more details.
 12//
 13// You should have received a copy of the GNU General Public License
 14// along with this program. If not, see <http://www.gnu.org/licenses/>.
 15
 16package util
 17
 18import (
 19	"errors"
 20	"html"
 21	"os"
 22	"os/signal"
 23	"os/user"
 24	"path/filepath"
 25	"strings"
 26	"unicode"
 27)
 28
 29// Lock creates a lockfile at the given path and creates a signal
 30// handler which removes the lockfile on interrupt or kill.
 31func Lock(path string) (err error) {
 32	_, err = os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0444)
 33	if err != nil {
 34		return
 35	}
 36
 37	// Setup unlock handler
 38	ch := make(chan os.Signal, 1)
 39	go func() {
 40		<-ch // Block until signal is received
 41		os.Remove(path)
 42		os.Exit(2)
 43	}()
 44	signal.Notify(ch, os.Interrupt, os.Kill)
 45
 46	return
 47}
 48
 49// Escape escapes the given data to make sure it is safe to use it as a
 50// filename. It also replaces spaces and other seperation characters
 51// with the '-' character. It returns an error if the escaped string is
 52// empty.
 53func Escape(name string) (escaped string, err error) {
 54	mfunc := func(r rune) rune {
 55		switch {
 56		case unicode.IsLetter(r):
 57			return r
 58		case unicode.IsNumber(r):
 59			return r
 60		case unicode.IsSpace(r):
 61			return '-'
 62		case unicode.IsPunct(r):
 63			return '-'
 64		}
 65
 66		return -1
 67	}
 68
 69	escaped = strings.Map(mfunc, html.UnescapeString(name))
 70	for strings.Contains(escaped, "--") {
 71		escaped = strings.Replace(escaped, "--", "-", -1)
 72	}
 73
 74	escaped = strings.TrimPrefix(escaped, "-")
 75	escaped = strings.TrimSuffix(escaped, "-")
 76
 77	if len(escaped) <= 0 {
 78		err = errors.New("couldn't escape title")
 79	}
 80
 81	return
 82}
 83
 84// EnvDefault returns the value of the given environment variable
 85// key if it is not empty. If it is empty it returns the fallback
 86// as an absolute path joined with the users home.
 87func EnvDefault(key, fallback string) string {
 88	dir := os.Getenv(key)
 89	if len(dir) > 0 {
 90		return dir
 91	}
 92
 93	var home string
 94	user, err := user.Current()
 95	if err == nil {
 96		home = user.HomeDir
 97	} else {
 98		home = os.Getenv("HOME")
 99	}
100
101	return filepath.Join(home, fallback)
102}
103
104// Username returns the username of the current user. It tries to
105// determine the username using os/user first and if that doesn't
106// work it returns the value of the USER environment variable.
107func Username() string {
108	var name string
109	user, err := user.Current()
110	if err == nil {
111		name = user.Username
112	} else {
113		name = os.Getenv("USER")
114	}
115
116	return name
117}