github.com/CyCoreSystems/ari@v4.8.4+incompatible/ext/audiouri/uri.go (about)

     1  // Package audiouri provides conversions for common sounds to asterisk-supported audio URIs
     2  package audiouri
     3  
     4  import (
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  	"time"
     9  )
    10  
    11  // SupportedPlaybackPrefixes is a list of valid prefixes
    12  // for media URIs.
    13  var SupportedPlaybackPrefixes = []string{
    14  	"sound", "recording", "number", "digits", "characters", "tone",
    15  }
    16  
    17  func init() {
    18  	sort.Strings(SupportedPlaybackPrefixes)
    19  }
    20  
    21  // WaitURI returns the set of media URIs for the
    22  // given period of silence.
    23  func WaitURI(t time.Duration) []string {
    24  	q := []string{}
    25  	for i := time.Duration(0); i <= t; i += time.Second {
    26  		q = append(q, "sound:silence/1")
    27  	}
    28  	return q
    29  }
    30  
    31  // NumberURI returns the media URI to play
    32  // the given number.
    33  func NumberURI(number int) string {
    34  	return fmt.Sprintf("number:%d", number)
    35  }
    36  
    37  // DigitsURI returns the set of media URIs to
    38  // play the given digits.
    39  func DigitsURI(digits string, hash string) []string {
    40  	// TODO: Strip anything which is not a digit or #
    41  
    42  	if strings.Contains(digits, "#") && hash != "" {
    43  		hash = "sound:char/" + hash
    44  
    45  		// Split the digits by each hash
    46  		pieces := strings.Split(digits, "#")
    47  
    48  		// Get the strings for each digit substring
    49  		newDigits := []string{}
    50  		for i, p := range pieces {
    51  			newDigits = append(newDigits, DigitsURI(p, hash)...)
    52  			if len(pieces) > i+1 {
    53  				// If this wasn't the last piece, add a hash
    54  				newDigits = append(newDigits, hash)
    55  			}
    56  		}
    57  		return newDigits
    58  	}
    59  
    60  	// Handle '*' to 'star' conversion
    61  	if strings.Contains(digits, "*") {
    62  		star := "sound:char/star"
    63  
    64  		// Split the digits by each *
    65  		pieces := strings.Split(digits, "*")
    66  
    67  		// Get the strings for each digit substring
    68  		newDigits := []string{}
    69  		for i, p := range pieces {
    70  			newDigits = append(newDigits, DigitsURI(p, hash)...)
    71  			if len(pieces) > i+1 {
    72  				// If this wasn't the last piece, add a star
    73  				newDigits = append(newDigits, star)
    74  			}
    75  		}
    76  		return newDigits
    77  	}
    78  
    79  	// Otherwise, we can simply use the normal "digits:" URI
    80  	if len(digits) < 1 {
    81  		return []string{}
    82  	}
    83  	return []string{"digits:" + digits}
    84  }
    85  
    86  // DateTimeURI returns the set of media URIs for playing
    87  // the current date and time.
    88  func DateTimeURI(t time.Time) (ret []string) {
    89  	ret = []string{}
    90  
    91  	ret = append(ret,
    92  		fmt.Sprintf("sound:digits/day-%d", t.Weekday()),
    93  		fmt.Sprintf("sound:digits/mon-%d", t.Month()-1),
    94  		NumberURI(t.Day()),
    95  	)
    96  
    97  	// Convert to 12-hour time
    98  	pm := false
    99  	hour := t.Hour()
   100  	switch {
   101  	case hour == 0:
   102  		hour = 12
   103  	case hour == 12:
   104  		pm = true
   105  	case hour > 12:
   106  		hour -= 12
   107  		pm = true
   108  	default:
   109  	}
   110  	ret = append(ret, NumberURI(hour))
   111  
   112  	// Humanize the minutes
   113  	minute := t.Minute()
   114  	switch {
   115  	case minute == 0:
   116  		ret = append(ret, "sound:digits/oclock")
   117  	case minute < 10:
   118  		ret = append(ret,
   119  			"sound:digits/oh",
   120  			NumberURI(minute),
   121  		)
   122  	default:
   123  		ret = append(ret, NumberURI(minute))
   124  	}
   125  
   126  	// Add am/pm suffix
   127  	if pm {
   128  		ret = append(ret, "sound:digits/p-m")
   129  	} else {
   130  		ret = append(ret, "sound:digits/a-m")
   131  	}
   132  
   133  	// Add the year
   134  	ret = append(ret, NumberURI(t.Year()))
   135  
   136  	return
   137  }
   138  
   139  // DurationURI returns the set of media URIs for playing
   140  // the given duration, in human terms (days, hours, minutes, seconds).
   141  // If any of these terms are zero, they will not be spoken.
   142  func DurationURI(dur time.Duration) (ret []string) {
   143  	days := int(dur.Hours() / 24)
   144  	hours := int(dur.Hours()) % 24
   145  	minutes := int(dur.Minutes()) % 60
   146  	seconds := int(dur.Seconds()) % 60
   147  
   148  	ret = []string{}
   149  
   150  	if days > 0 {
   151  		ret = append(ret, NumberURI(days))
   152  		if days > 1 {
   153  			ret = append(ret, "sound:time/days")
   154  		} else {
   155  			ret = append(ret, "sound:time/day")
   156  		}
   157  	}
   158  
   159  	if hours > 0 {
   160  		ret = append(ret, NumberURI(hours))
   161  		if hours > 1 {
   162  			ret = append(ret, "sound:time/hours")
   163  		} else {
   164  			ret = append(ret, "sound:time/hour")
   165  		}
   166  	}
   167  
   168  	if minutes > 0 {
   169  		ret = append(ret, NumberURI(minutes))
   170  		if minutes > 1 {
   171  			ret = append(ret, "sound:time/minutes")
   172  		} else {
   173  			ret = append(ret, "sound:time/minute")
   174  		}
   175  	}
   176  
   177  	if seconds > 0 {
   178  		ret = append(ret, NumberURI(seconds))
   179  		if seconds > 1 {
   180  			ret = append(ret, "sound:time/seconds")
   181  		} else {
   182  			ret = append(ret, "sound:time/second")
   183  		}
   184  	}
   185  
   186  	return
   187  }
   188  
   189  // RecordingURI returns the media URI for playing an
   190  // Asterisk StoredRecording
   191  func RecordingURI(name string) string {
   192  	return "recording:" + name
   193  }
   194  
   195  // ToneURI returns the media URI for playing the
   196  // given tone, which may be a system-defined indication
   197  // or an explicit tone pattern construction.
   198  func ToneURI(name string) string {
   199  	return "tone:" + name
   200  }
   201  
   202  // Check checks if the audio URI is formatted properly
   203  func Check(uri string) error {
   204  	l := strings.Split(uri, ":")
   205  	if len(l) != 2 {
   206  		return fmt.Errorf("Audio URI %s is not formatted properly", uri)
   207  	}
   208  
   209  	if sort.SearchStrings(SupportedPlaybackPrefixes, l[0]) == len(SupportedPlaybackPrefixes) {
   210  		return fmt.Errorf("Audio URI prefix %s not supported", l[0])
   211  	}
   212  
   213  	return nil
   214  }