-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
121 lines (112 loc) · 4.58 KB
/
main.go
File metadata and controls
121 lines (112 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"encoding/base64"
"encoding/xml"
"fmt"
"os"
"strings"
"github.com/gorilla/feeds"
"github.com/rwinkhart/backtone/atom"
"github.com/rwinkhart/backtone/websrc"
"github.com/rwinkhart/go-boilerplate/other"
)
const cfgPath = "/etc/backtone.xml"
// feedFieldInfo provides the string value for a given field in the parent feed
// and specifies which index in the regex capture group to extract the same field
// from per individual news item.
// An index of -1 can be used to use the same value as the parent feed.
// An index of -2 can be used to use a default (placeholder) value.
type feedFieldInfoT struct {
Parent string `xml:"parent,omitempty"`
CaptureGroupConnector []string `xml:"captureGroupConnector,omitempty"`
CaptureGroupIndex []int8 `xml:"captureGroupIndex,omitempty"`
}
type feedT struct {
Title feedFieldInfoT `xml:"title"`
Link feedFieldInfoT `xml:"link"`
Description feedFieldInfoT `xml:"description"`
AuthorName feedFieldInfoT `xml:"authorName"`
AuthorEmail feedFieldInfoT `xml:"authorEmail"`
}
type inputT struct {
FlareSolverrEndpoint string `xml:"flareSolverrEndpoint,omitempty"`
APIMethodEndpointPayload string `xml:"apiMethodEndpointPayload,omitempty"`
Regex string `xml:"regex"`
LoadSeconds float32 `xml:"loadSeconds"`
MaxFeedItems int `xml:"maxFeedItems"`
Feed feedT `xml:"feed"`
}
func main() {
// handle input argument (XML)
if len(os.Args) < 2 {
demoInputBytes, _ := xml.MarshalIndent(
inputT{
FlareSolverrEndpoint: "http://127.0.0.1:8191",
Regex: "PLACEHOLDER",
LoadSeconds: 2.5,
MaxFeedItems: 10,
Feed: feedT{
Title: feedFieldInfoT{Parent: "Demo Title", CaptureGroupIndex: []int8{0}},
Link: feedFieldInfoT{Parent: "https://example.com/", CaptureGroupIndex: []int8{1}},
Description: feedFieldInfoT{Parent: "Demo description", CaptureGroupConnector: []string{"Prefix - ", " - Middle - ", " - Suffix"}, CaptureGroupIndex: []int8{1, 3}},
AuthorName: feedFieldInfoT{Parent: "John Doe", CaptureGroupIndex: []int8{3}},
AuthorEmail: feedFieldInfoT{Parent: "johndoe@example.com", CaptureGroupIndex: []int8{4}},
},
},
"",
" ",
)
other.PrintError(os.Args[0]+" must be called with valid base64-encoded XML input using the following schema:\n\n"+string(demoInputBytes), 1)
}
// decode base64 input XML
decodedXML, err := base64.StdEncoding.DecodeString(os.Args[1])
if err != nil {
other.PrintError("Failed to decode base64 input XML: "+err.Error(), 1)
}
var inputInfo inputT
if err := xml.Unmarshal(decodedXML, &inputInfo); err != nil {
other.PrintError("Failed to unmarshal input XML: "+err.Error(), 1)
}
var rawString string
if inputInfo.FlareSolverrEndpoint != "" {
rawString, err = websrc.GetByScrape(inputInfo.FlareSolverrEndpoint, inputInfo.Feed.Link.Parent, inputInfo.LoadSeconds)
if err != nil {
other.PrintError("Failed to scrape HTML content: "+err.Error(), 1)
}
} else if inputInfo.APIMethodEndpointPayload != "" {
apiInfoSplit := strings.Split(inputInfo.APIMethodEndpointPayload, "@")
rawString, err = websrc.GetByAPIJson(apiInfoSplit[0], apiInfoSplit[1], []byte(apiInfoSplit[2]))
if err != nil {
other.PrintError("Failed to get API response: "+err.Error(), 1)
}
} else {
other.PrintError("Either FlareSolverrEndpoint or APIMethodPayload must be specified", 1)
}
atomXML, err := atom.GetFromString(
&feeds.Feed{
Title: inputInfo.Feed.Title.Parent,
Link: &feeds.Link{Href: inputInfo.Feed.Link.Parent},
Description: inputInfo.Feed.Description.Parent,
Author: &feeds.Author{Name: inputInfo.Feed.AuthorName.Parent, Email: inputInfo.Feed.AuthorEmail.Parent},
},
&rawString,
inputInfo.Regex,
atom.IndicesT{
TitleC: inputInfo.Feed.Title.CaptureGroupConnector,
TitleI: inputInfo.Feed.Title.CaptureGroupIndex,
LinkC: inputInfo.Feed.Link.CaptureGroupConnector,
LinkI: inputInfo.Feed.Link.CaptureGroupIndex,
DescriptionC: inputInfo.Feed.Description.CaptureGroupConnector,
DescriptionI: inputInfo.Feed.Description.CaptureGroupIndex,
AuthorNameC: inputInfo.Feed.AuthorName.CaptureGroupConnector,
AuthorNameI: inputInfo.Feed.AuthorName.CaptureGroupIndex,
AuthorEmailC: inputInfo.Feed.AuthorEmail.CaptureGroupConnector,
AuthorEmailI: inputInfo.Feed.AuthorEmail.CaptureGroupIndex,
},
inputInfo.MaxFeedItems,
)
if err != nil {
other.PrintError("Failed to generate Atom RSS feed from HTML:\n\n"+rawString+"\n\n"+err.Error(), 1)
}
fmt.Println(*atomXML)
}