Skip to content

Commit

Permalink
handle big numbers and logfile in dockerfile
Browse files Browse the repository at this point in the history
  • Loading branch information
trinidz committed Nov 26, 2024
1 parent 7b02056 commit 15bda49
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 78 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ rssnotes is a nostr relay that functions as an rss to nostr bridge by creating n
- The rssnotes relay also has its own pubkey. The rssnotes relay pubkey automatically follows all of the rss feed profiles. So if you login to nostr as the rssnotes relay you will see all of your RSS feeds.
- Option to import and export multiple RSS feeds at once using an opml file.
- Option to automatically delete old notes.
- Selection of relay metrics dislayed on main page. (Metrics are per session and will reset if relay is restarted.)
- Selection of relay metrics dislayed on main page. (Displayed metrics other than CURRENT FEEDS are per session and will reset if relay is restarted.)
- Prometheus metrics available on /metrics path.
- Search bar
- Relay logs exposed on the /log path.
Expand Down
4 changes: 2 additions & 2 deletions dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ COPY go.mod ./
COPY go.sum ./
RUN go mod download

RUN touch logfile.log

COPY . .

# Build the go binary
RUN go build -o rssnotes .

# Stage 2: Create a image to run the Go application
#FROM ubuntu:latest
#FROM debian:bookworm-slim
FROM alpine:latest

ENV PORT=3334
Expand Down
67 changes: 0 additions & 67 deletions feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,73 +283,6 @@ func getPrivateKeyFromFeedUrl(url string, secret string) string {
return hex.EncodeToString(r)
}

func GetConverterRules() []md.Rule {
return []md.Rule{
{
Filter: []string{"h1", "h2", "h3", "h4", "h5", "h6"},
Replacement: func(content string, selection *goquery.Selection, opt *md.Options) *string {
content = strings.TrimSpace(content)
return md.String(content)
},
},
{
Filter: []string{"img"},
AdvancedReplacement: func(content string, selec *goquery.Selection, opt *md.Options) (md.AdvancedResult, bool) {
src := selec.AttrOr("src", "")
src = strings.TrimSpace(src)
if src == "" {
return md.AdvancedResult{
Markdown: "",
}, false
}

src = opt.GetAbsoluteURL(selec, src, "")

text := fmt.Sprintf("\n%s\n", src)
return md.AdvancedResult{
Markdown: text,
}, false
},
},
{
Filter: []string{"a"},
AdvancedReplacement: func(content string, selec *goquery.Selection, opt *md.Options) (md.AdvancedResult, bool) {
// if there is no href, no link is used. So just return the content inside the link
href, ok := selec.Attr("href")
if !ok || strings.TrimSpace(href) == "" || strings.TrimSpace(href) == "#" {
return md.AdvancedResult{
Markdown: content,
}, false
}

href = opt.GetAbsoluteURL(selec, href, "")

// having multiline content inside a link is a bit tricky
content = md.EscapeMultiLine(content)

// if there is no link content (for example because it contains an svg)
// the 'title' or 'aria-label' attribute is used instead.
if strings.TrimSpace(content) == "" {
content = selec.AttrOr("title", selec.AttrOr("aria-label", ""))
}

// a link without text won't de displayed anyway
if content == "" {
return md.AdvancedResult{
Markdown: "",
}, false
}

replacement := fmt.Sprintf("%s (%s)", content, href)

return md.AdvancedResult{
Markdown: replacement,
}, false
},
},
}
}

func checkAllFeeds() {
currentEntities, err := getSavedEntities()
if err != nil {
Expand Down
7 changes: 2 additions & 5 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,15 +669,12 @@ func getPrometheusMetric(promParam *prometheus.Desc) string {
if strings.HasPrefix(line, promMetricName) {
//fmt.Println(line)
count := strings.Split(line, " ")[1]
countInt, err := strconv.Atoi(count)
countInt64, err := strconv.ParseInt(count, 10, 64)
if err != nil {
log.Print("[ERROR]", err)
return "?"
}
if countInt < 0 || countInt > 9999 {
return "+9999"
}
return count
return nearestThousandFormat(float64(countInt64))
}
}
return "?"
Expand Down
71 changes: 71 additions & 0 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
Expand All @@ -12,6 +13,9 @@ import (
"sort"
"strings"
"time"

md "github.com/JohannesKaufmann/html-to-markdown"
"github.com/PuerkitoBio/goquery"
)

var validSchemas = []string{"https", "http"}
Expand Down Expand Up @@ -67,6 +71,73 @@ func IconUrlExists(url string) bool {
return true
}

func GetConverterRules() []md.Rule {
return []md.Rule{
{
Filter: []string{"h1", "h2", "h3", "h4", "h5", "h6"},
Replacement: func(content string, selection *goquery.Selection, opt *md.Options) *string {
content = strings.TrimSpace(content)
return md.String(content)
},
},
{
Filter: []string{"img"},
AdvancedReplacement: func(content string, selec *goquery.Selection, opt *md.Options) (md.AdvancedResult, bool) {
src := selec.AttrOr("src", "")
src = strings.TrimSpace(src)
if src == "" {
return md.AdvancedResult{
Markdown: "",
}, false
}

src = opt.GetAbsoluteURL(selec, src, "")

text := fmt.Sprintf("\n%s\n", src)
return md.AdvancedResult{
Markdown: text,
}, false
},
},
{
Filter: []string{"a"},
AdvancedReplacement: func(content string, selec *goquery.Selection, opt *md.Options) (md.AdvancedResult, bool) {
// if there is no href, no link is used. So just return the content inside the link
href, ok := selec.Attr("href")
if !ok || strings.TrimSpace(href) == "" || strings.TrimSpace(href) == "#" {
return md.AdvancedResult{
Markdown: content,
}, false
}

href = opt.GetAbsoluteURL(selec, href, "")

// having multiline content inside a link is a bit tricky
content = md.EscapeMultiLine(content)

// if there is no link content (for example because it contains an svg)
// the 'title' or 'aria-label' attribute is used instead.
if strings.TrimSpace(content) == "" {
content = selec.AttrOr("title", selec.AttrOr("aria-label", ""))
}

// a link without text won't de displayed anyway
if content == "" {
return md.AdvancedResult{
Markdown: "",
}, false
}

replacement := fmt.Sprintf("%s (%s)", content, href)

return md.AdvancedResult{
Markdown: replacement,
}, false
},
},
}
}

func GetRelayListFromFile(filePath string) []string {
file, err := os.ReadFile(filePath)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type Settings struct {
RelayIcon string `envconfig:"RELAY_ICON" default:"https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/commafeed.png"`
RandomSecret string `envconfig:"RANDOM_SECRET" required:"true"`
OwnerPubkey string `envconfig:"OWNER_PUBKEY"`
Version string `envconfig:"VERSION" default:"0.0.10"`
Version string `envconfig:"VERSION" default:"0.0.11"`

LogLevel string `envconfig:"LOG_LEVEL" default:"WARN"`
Port string `envconfig:"PORT" default:"3334"`
Expand Down Expand Up @@ -165,8 +165,8 @@ func main() {
mux.HandleFunc("GET /detail", handleImportDetail)
mux.HandleFunc("GET /export", handleExportOpml)
mux.HandleFunc("GET /delete", handleDeleteFeed)
mux.Handle("GET /metrics", promhttp.Handler())

mux.Handle("/metrics", promhttp.Handler())
mux.HandleFunc("GET /health", handleHealth)
mux.HandleFunc("GET /log", handleLog)

Expand Down
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ new: build
@go build -o bin/$(BINARY_NAME) && ./bin/$(BINARY_NAME)

test:
@go test -v ./...
@go test -v ./...
132 changes: 132 additions & 0 deletions numbers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package main

import (
"math"
"strconv"
"strings"
)

// credit to https://github.com/DeyV/gotools/blob/master/numbers.go
func roundPrec(x float64, prec int) float64 {
if math.IsNaN(x) || math.IsInf(x, 0) {
return x
}

sign := 1.0
if x < 0 {
sign = -1
x *= -1
}

var rounder float64
pow := math.Pow(10, float64(prec))
intermed := x * pow
_, frac := math.Modf(intermed)

if frac >= 0.5 {
rounder = math.Ceil(intermed)
} else {
rounder = math.Floor(intermed)
}

return rounder / pow * sign
}

func numberFormat(number float64, decimals int, decPoint, thousandsSep string) string {
if math.IsNaN(number) || math.IsInf(number, 0) {
number = 0
}

var ret string
var negative bool

if number < 0 {
number *= -1
negative = true
}

d, fract := math.Modf(number)

if decimals <= 0 {
fract = 0
} else {
pow := math.Pow(10, float64(decimals))
fract = roundPrec(fract*pow, 0)
}

if thousandsSep == "" {
ret = strconv.FormatFloat(d, 'f', 0, 64)
} else if d >= 1 {
var x float64
for d >= 1 {
d, x = math.Modf(d / 1000)
x = x * 1000
ret = strconv.FormatFloat(x, 'f', 0, 64) + ret
if d >= 1 {
ret = thousandsSep + ret
}
}
} else {
ret = "0"
}

fracts := strconv.FormatFloat(fract, 'f', 0, 64)

// "0" pad left
for i := len(fracts); i < decimals; i++ {
fracts = "0" + fracts
}

ret += decPoint + fracts

if negative {
ret = "-" + ret
}
return ret
}

func roundInt(input float64) int {
var result float64

if input < 0 {
result = math.Ceil(input - 0.5)
} else {
result = math.Floor(input + 0.5)
}

// only interested in integer, ignore fractional
i, _ := math.Modf(result)

return int(i)
}

func formatNumber(input float64) string {
x := roundInt(input)
xFormatted := numberFormat(float64(x), 2, ".", ",")
return xFormatted
}

func nearestThousandFormat(num float64) string {

if math.Abs(num) < 999.5 {
xNum := formatNumber(num)
xNumStr := xNum[:len(xNum)-3]
return string(xNumStr)
}

xNum := formatNumber(num)
// first, remove the .00 then convert to slice
xNumStr := xNum[:len(xNum)-3]
xNumCleaned := strings.Replace(xNumStr, ",", " ", -1)
xNumSlice := strings.Fields(xNumCleaned)
count := len(xNumSlice) - 2
unit := [4]string{"k", "m", "b", "t"}
xPart := unit[count]

afterDecimal := ""
if xNumSlice[1][0] != 0 {
afterDecimal = "." + string(xNumSlice[1][0])
}
final := xNumSlice[0] + afterDecimal + xPart
return final
}

0 comments on commit 15bda49

Please sign in to comment.