utils.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package feed
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/url"
  6. "regexp"
  7. "slices"
  8. "strings"
  9. "time"
  10. )
  11. var (
  12. ErrNoContent = errors.New("failed to retrieve any content")
  13. ErrPartialContent = errors.New("failed to retrieve some of the content")
  14. )
  15. func percentChange(current, previous float64) float64 {
  16. return (current/previous - 1) * 100
  17. }
  18. func extractDomainFromUrl(u string) string {
  19. if u == "" {
  20. return ""
  21. }
  22. parsed, err := url.Parse(u)
  23. if err != nil {
  24. return ""
  25. }
  26. return strings.TrimPrefix(strings.ToLower(parsed.Host), "www.")
  27. }
  28. func SvgPolylineCoordsFromYValues(width float64, height float64, values []float64) string {
  29. if len(values) < 2 {
  30. return ""
  31. }
  32. verticalPadding := height * 0.02
  33. height -= verticalPadding * 2
  34. coordinates := make([]string, len(values))
  35. distanceBetweenPoints := width / float64(len(values)-1)
  36. min := slices.Min(values)
  37. max := slices.Max(values)
  38. for i := range values {
  39. coordinates[i] = fmt.Sprintf(
  40. "%.2f,%.2f",
  41. float64(i)*distanceBetweenPoints,
  42. ((max-values[i])/(max-min))*height+verticalPadding,
  43. )
  44. }
  45. return strings.Join(coordinates, " ")
  46. }
  47. func maybeCopySliceWithoutZeroValues[T int | float64](values []T) []T {
  48. if len(values) == 0 {
  49. return values
  50. }
  51. for i := range values {
  52. if values[i] != 0 {
  53. continue
  54. }
  55. c := make([]T, 0, len(values)-1)
  56. for i := range values {
  57. if values[i] != 0 {
  58. c = append(c, values[i])
  59. }
  60. }
  61. return c
  62. }
  63. return values
  64. }
  65. var urlSchemePattern = regexp.MustCompile(`^[a-z]+:\/\/`)
  66. func stripURLScheme(url string) string {
  67. return urlSchemePattern.ReplaceAllString(url, "")
  68. }
  69. func limitStringLength(s string, max int) (string, bool) {
  70. asRunes := []rune(s)
  71. if len(asRunes) > max {
  72. return string(asRunes[:max]), true
  73. }
  74. return s, false
  75. }
  76. func parseRFC3339Time(t string) time.Time {
  77. parsed, err := time.Parse(time.RFC3339, t)
  78. if err != nil {
  79. return time.Now()
  80. }
  81. return parsed
  82. }