Compare commits

...

3 Commits

Author SHA1 Message Date
0d8edc0547 Implement web fetch 2025-02-07 14:37:36 -08:00
6b278a081c Fix render error logging 2025-02-07 14:16:43 -08:00
9c4887c93e Remove inline style 2025-02-07 14:08:54 -08:00
10 changed files with 108 additions and 8 deletions

View File

@ -26,11 +26,14 @@ tmp/intake item add -s feedtest --id o --title "TTS 30s" --tts 30
tmp/intake item add -s feedtest --id p --title "TTS 10d" --tts 864000
tmp/intake item add -s feedtest --id q --title "TTS -10d" --tts "-864000"
tmp/intake action add -s feedtest -a fetch -- jq -cn '{id: "0", title: "Returned by fetch"}'
tmp/intake source add -s spook
tmp/intake action add -s spook -a spookier -- jq -c '.title = .title + "o"'
tmp/intake item add -s spook --id boo --title "Boo" --action '{"spookier": true}'
tmp/intake source add -s nothing
tmp/intake action add -s nothing -a fetch -- true
tmp/intake channel add -c all -s feedtest
tmp/intake channel add -c all -s spook

View File

@ -2,7 +2,7 @@
{{ define "content" -}}
<article class="center">
<span class="feed-controls" style="display: flex; justify-content: space-between;">
<span class="feed-controls flex-between">
<a href="?hidden={{ .ShowHidden }}&page={{ page .Page -1 }}&count={{ .Count }}">&lt;--</a>
<a href="/">Home</a>
<span>

16
web/html/fetch.html Normal file
View File

@ -0,0 +1,16 @@
{{ define "title" }}Intake - fetch result for {{ .Source }}{{ end }}
{{ define "content" -}}
<article class="center">
<span class="feed-controls">Fetch results for <a href="/source/{{ .Source }}">{{ .Source }}</a></span>
</article>
<article>
<p>{{ .Added }} new items, {{ .Updated }} updated items, {{ .Deleted }} deleted items</p>
<ul>
{{ range .Items -}}
<li><a href="/item/{{ .Source }}/{{ .Id }}">{{ or .Title .Id | raw }}</a></li>
{{ end -}}
</ul>
</article>
{{- end }}

View File

@ -27,6 +27,12 @@
<table class="intake-sources">
{{ range .Sources }}
<tr>
<td>
<form method="post" action="/source/{{ .Name }}/fetch">
<button type="submit">fetch</button>
</form>
</td>
</td>
<td><a href="/source/{{ .Name }}">{{ .Name }}</a></td>
</tr>
{{ end }}

View File

@ -148,10 +148,25 @@ type LoginData struct {
Error string
}
func Login(writer io.Writer, data LoginData) error {
func Login(writer io.Writer, data LoginData) {
err := login.Execute(writer, data)
if err != nil {
log.Printf("render error: %v", err)
log.Printf("error: failed to render login: %v", err)
}
}
var fetch = load("fetch.html")
type FetchData struct {
Source string
Added int
Updated int
Deleted int
Items []core.Item
}
func Fetch(writer io.Writer, data FetchData) {
if err := fetch.Execute(writer, data); err != nil {
log.Printf("error: failed to render fetch: %v", err)
}
return err
}

View File

@ -13,6 +13,10 @@ article {
.feed-controls {
font-size: 1.2em;
}
.flex-between {
display: flex;
justify-content: space-between;
}
.item-title {
font-size: 1.4em;
}

View File

@ -13,4 +13,5 @@
>Submit</button>
</form>
<p id="errors">{{ .Error }}</p>
</article>
{{ end }}

View File

@ -5,7 +5,6 @@ import (
"database/sql"
"errors"
"fmt"
"log"
"net/http"
"time"
@ -63,9 +62,7 @@ func renderLoginWithErrorMessage(writer http.ResponseWriter, req *http.Request,
}
data := html.LoginData{Error: message}
if err := html.Login(writer, data); err != nil {
log.Printf("render error: %v", err)
}
html.Login(writer, data)
}
func (env *Env) authed(handler http.HandlerFunc) http.HandlerFunc {

View File

@ -40,6 +40,7 @@ func RunServer(db core.DB, addr string, port string) {
handleFunc("GET /htmx.org@2.0.4.js", env.getScript, logged)
handleFunc("POST /login", env.login, logged)
handleFunc("GET /source/{source}", env.getSource, env.authed, logged)
handleFunc("POST /source/{source}/fetch", env.fetchSource, env.authed, logged)
handleFunc("GET /channel/{channel}", env.getChannel, env.authed, logged)
handleFunc("GET /item/{source}/{id}", env.getItem, env.authed, logged)
handleFunc("DELETE /item/{source}/{id}", env.deleteItem, env.authed, logged)

View File

@ -1,7 +1,10 @@
package web
import (
"fmt"
"log"
"net/http"
"time"
"github.com/Jaculabilis/intake/core"
"github.com/Jaculabilis/intake/web/html"
@ -38,3 +41,57 @@ func (env *Env) getSource(writer http.ResponseWriter, req *http.Request) {
}
html.Feed(writer, data)
}
func (env *Env) fetchSource(writer http.ResponseWriter, req *http.Request) {
source := req.PathValue("source")
if exists, err := core.SourceExists(env.db, source); !exists || err != nil {
http.NotFound(writer, req)
return
}
state, err := core.GetState(env.db, source)
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to get state: %v", err.Error()), 500)
return
}
envs, err := core.GetEnvs(env.db, source)
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to get envs: %v", err.Error()), 500)
return
}
argv, err := core.GetArgvForAction(env.db, source, "fetch")
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to get fetch argv: %v", err.Error()), 500)
return
}
postProcess, err := core.GetSourcePostProcessor(env.db, source)
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to get post-processor: %v", err.Error()), 500)
return
}
items, newState, err := core.Execute(source, argv, envs, state, "", time.Minute, postProcess)
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to execute fetch: %v", err.Error()), 500)
return
}
added, deleted, err := core.UpdateWithFetchedItems(env.db, source, newState, items, time.Now())
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to update: %v", err.Error()), 500)
return
}
log.Printf("%s added %d items, updated %d items, and deleted %d items", source, added, len(items)-added, deleted)
data := html.FetchData{
Source: source,
Added: added,
Updated: len(items) - added,
Deleted: deleted,
Items: items,
}
html.Fetch(writer, data)
}