v35: Add git commit/push to deploy script

This commit is contained in:
primal
2026-01-30 15:58:49 -05:00
parent 8192bce301
commit a5fe2962c3
5 changed files with 67 additions and 28 deletions
+5 -3
View File
@@ -134,6 +134,7 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
Type string `json:"type,omitempty"`
Status string `json:"status,omitempty"`
PublishStatus string `json:"publish_status,omitempty"`
Language string `json:"language,omitempty"`
}
type DomainInfo struct {
@@ -162,7 +163,7 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
// Now get feeds for these domains
if len(hosts) > 0 {
feedRows, err := c.db.Query(`
SELECT source_host, url, title, type, status, publish_status
SELECT source_host, url, title, type, status, publish_status, language
FROM feeds
WHERE source_host = ANY($1)
ORDER BY source_host, url
@@ -173,14 +174,15 @@ func (c *Crawler) handleAPIDomains(w http.ResponseWriter, r *http.Request) {
for feedRows.Next() {
var host string
var f FeedInfo
var title, feedType, status, publishStatus *string
if err := feedRows.Scan(&host, &f.URL, &title, &feedType, &status, &publishStatus); err != nil {
var title, feedType, status, publishStatus, language *string
if err := feedRows.Scan(&host, &f.URL, &title, &feedType, &status, &publishStatus, &language); err != nil {
continue
}
f.Title = StringValue(title)
f.Type = StringValue(feedType)
f.Status = StringValue(status)
f.PublishStatus = StringValue(publishStatus)
f.Language = StringValue(language)
feedsByHost[host] = append(feedsByHost[host], f)
}
// Attach feeds to domains
+24 -16
View File
@@ -7,6 +7,7 @@ import (
"html/template"
"net/http"
"net/url"
"strings"
"time"
"github.com/haileyok/atproto-oauth-golang/helpers"
@@ -64,14 +65,29 @@ func (m *OAuthManager) HandleLogin(w http.ResponseWriter, r *http.Request) {
// If handle is provided, start OAuth flow
handle := r.URL.Query().Get("handle")
if handle != "" {
// Save handle to cookie for prefill on next visit
http.SetCookie(w, &http.Cookie{
Name: "last_handle",
Value: handle,
Path: "/",
MaxAge: 86400 * 365, // 1 year
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
m.startOAuthFlow(w, r, handle)
return
}
// Get last handle from cookie for prefill
lastHandle := ""
if cookie, err := r.Cookie("last_handle"); err == nil {
lastHandle = cookie.Value
}
// Serve login page
w.Header().Set("Content-Type", "text/html; charset=utf-8")
tmpl := template.Must(template.New("login").Parse(loginPageHTML))
tmpl.Execute(w, nil)
tmpl.Execute(w, map[string]string{"LastHandle": lastHandle})
}
// startOAuthFlow initiates the OAuth flow for a given handle
@@ -79,6 +95,11 @@ func (m *OAuthManager) startOAuthFlow(w http.ResponseWriter, r *http.Request, ha
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
defer cancel()
// Auto-append .bsky.social if handle has no dots
if !strings.Contains(handle, ".") {
handle = handle + ".bsky.social"
}
fmt.Printf("OAuth: starting flow for handle: %s\n", handle)
// Resolve handle to DID
@@ -168,20 +189,7 @@ func (m *OAuthManager) startOAuthFlow(w http.ResponseWriter, r *http.Request, ha
fmt.Printf("OAuth: redirecting to: %s\n", authURL.String())
// Use JavaScript redirect to preserve browser security headers
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprintf(w, `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to authorization server...</p>
<script>window.location.href = %q;</script>
<noscript><a href="%s">Click here to continue</a></noscript>
</body>
</html>`, authURL.String(), authURL.String())
http.Redirect(w, r, authURL.String(), http.StatusFound)
}
// HandleCallback handles the OAuth callback
@@ -453,7 +461,7 @@ const loginPageHTML = `<!DOCTYPE html>
<form id="loginForm" action="/auth/login" method="get">
<div class="form-group">
<label for="handle">Bluesky Handle</label>
<input type="text" id="handle" name="handle" placeholder="handle.bsky.social" required autofocus>
<input type="text" id="handle" name="handle" placeholder="username or full.handle" value="{{.LastHandle}}" required autofocus>
</div>
<button type="submit" class="login-btn" id="loginBtn">
+16 -2
View File
@@ -1,6 +1,6 @@
#!/bin/bash
# Deploy script - increments version and relaunches container
# Usage: ./scripts/deploy.sh
# Deploy script - increments version, commits, pushes, and relaunches container
# Usage: ./scripts/deploy.sh [optional commit message]
set -e
@@ -22,6 +22,20 @@ sed -i '' "s/>v${CURRENT}</>v${NEW}</" templates.go
echo "Version: v${CURRENT} -> v${NEW}"
# Build commit message
if [ -n "$1" ]; then
COMMIT_MSG="v${NEW}: $1"
else
COMMIT_MSG="v${NEW}"
fi
# Commit and push
git add -A
git commit -m "$COMMIT_MSG"
git push
echo "Committed: $COMMIT_MSG"
# Rebuild and relaunch
docker compose up -d --build
+20 -6
View File
@@ -131,6 +131,10 @@ function initDashboard() {
html += `<div class="feed-row" style="display: flex; align-items: center; padding: 4px 0; font-size: 12px;">`;
// Language indicator (fixed width)
const lang = f.language || '';
html += `<span style="display: inline-block; width: 24px; color: #666; font-size: 10px; font-family: monospace; text-align: center;">${escapeHtml(lang)}</span>`;
// Feed status buttons
html += renderStatusBtns(feedStatus, 'feed', f.url, f.status);
@@ -141,7 +145,7 @@ function initDashboard() {
feedPath = urlObj.pathname + urlObj.search;
} catch (e) {}
const displayText = f.title ? `${feedPath} - ${f.title}` : feedPath;
html += `<span class="feed-title" style="color: #888; cursor: pointer; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="${escapeHtml(f.url)}">${escapeHtml(displayText)}</span>`;
html += `<span class="feed-title" style="color: #fff; cursor: pointer; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="${escapeHtml(f.url)}">${escapeHtml(displayText)}</span>`;
// Feed type
if (f.type) {
@@ -170,6 +174,10 @@ function initDashboard() {
html += `<div class="feed-row" style="display: flex; align-items: flex-start; padding: 8px 10px; border-bottom: 1px solid #202020;">`;
// Language indicator (fixed width)
const lang = f.language || '';
html += `<span style="display: inline-block; width: 24px; color: #666; font-size: 10px; font-family: monospace; text-align: center; padding-top: 4px;">${escapeHtml(lang)}</span>`;
// Status buttons (pass/hold/skip + fail indicator if errors)
html += `<div style="padding-top: 2px;">${renderStatusBtns(status, 'feed', f.url, f.status)}</div>`;
@@ -357,7 +365,7 @@ function initDashboard() {
// Description
if (info.description) {
html += `<div style="color: #aaa; margin-bottom: 10px; font-size: 0.9em;">${escapeHtml(info.description)}</div>`;
html += `<div style="color: #fff; margin-bottom: 10px; font-size: 0.9em;">${escapeHtml(info.description)}</div>`;
}
// Info row
@@ -384,7 +392,7 @@ function initDashboard() {
if (item.title && item.link) {
html += `<a href="${escapeHtml(item.link)}" target="_blank" style="color: #0af; text-decoration: none;">${escapeHtml(item.title)}</a>`;
} else if (item.title) {
html += `<span style="color: #ccc;">${escapeHtml(item.title)}</span>`;
html += `<span style="color: #fff;">${escapeHtml(item.title)}</span>`;
}
if (item.pub_date) {
const date = new Date(item.pub_date);
@@ -438,6 +446,7 @@ function initDashboard() {
}
// Show all domains view
// statusFilter can be: 'hold', 'pass', 'skip', 'fail', or 'feeds' (special: has_feeds=true)
async function showDomains(statusFilter = null) {
currentView = 'domains';
currentDomain = null;
@@ -466,7 +475,11 @@ function initDashboard() {
async function loadMore() {
try {
let url = `/api/domains?limit=${limit}&offset=${offset}&sort=alpha`;
if (statusFilter) url += `&status=${statusFilter}`;
if (statusFilter === 'feeds') {
url += `&has_feeds=true`;
} else if (statusFilter) {
url += `&status=${statusFilter}`;
}
const resp = await fetch(url);
const domains = await resp.json();
@@ -705,7 +718,7 @@ function initDashboard() {
// Description
if (info.description) {
html += `<div style="color: #aaa; margin-bottom: 15px;">${escapeHtml(info.description)}</div>`;
html += `<div style="color: #fff; margin-bottom: 15px;">${escapeHtml(info.description)}</div>`;
}
// Info table
@@ -734,7 +747,7 @@ function initDashboard() {
if (item.title && item.link) {
html += `<a href="${escapeHtml(item.link)}" target="_blank" style="color: #0af; text-decoration: none;">${escapeHtml(item.title)}</a>`;
} else if (item.title) {
html += `<span style="color: #ccc;">${escapeHtml(item.title)}</span>`;
html += `<span style="color: #fff;">${escapeHtml(item.title)}</span>`;
}
if (item.pub_date) {
const date = new Date(item.pub_date);
@@ -864,6 +877,7 @@ function initDashboard() {
<div style="margin-bottom: 10px;"><span style="color: #0af;">/domains</span> - List all domains</div>
<div style="margin-bottom: 10px;"><span style="color: #0af;">/feeds</span> - List all feeds</div>
<div style="margin-bottom: 10px;"><span style="color: #0af;">d:hold d:pass d:skip d:fail</span> - Filter domains by status</div>
<div style="margin-bottom: 10px;"><span style="color: #0af;">d:feeds</span> - Filter domains with discovered feeds</div>
<div style="margin-bottom: 10px;"><span style="color: #0af;">f:hold f:pass f:skip f:fail</span> - Filter feeds by status</div>
<div style="margin-bottom: 20px;"><span style="color: #0af;">[text]</span> - Search feeds</div>
<div style="color: #666;">Click domain/feed name to drill down. Click status buttons to set status.</div>
+2 -1
View File
@@ -512,6 +512,7 @@ const dashboardHTML = `<!DOCTYPE html>
<button class="cmd-btn" data-cmd="domains:pass">d:pass</button>
<button class="cmd-btn" data-cmd="domains:skip">d:skip</button>
<button class="cmd-btn" data-cmd="domains:fail">d:fail</button>
<button class="cmd-btn" data-cmd="domains:feeds">d:feeds</button>
<span style="color: #333; margin: 0 4px;">|</span>
<button class="cmd-btn" data-cmd="feeds:hold">f:hold</button>
<button class="cmd-btn" data-cmd="feeds:pass">f:pass</button>
@@ -533,7 +534,7 @@ const dashboardHTML = `<!DOCTYPE html>
<div id="output"></div>
</div>
<div style="color: #333; font-size: 11px; margin-top: 10px;">v26</div>
<div style="color: #333; font-size: 11px; margin-top: 10px;">v35</div>
<div class="updated" id="updatedAt">Last updated: {{.UpdatedAt.Format "2006-01-02 15:04:05"}}</div>
</body>