Update to use commons package
- Rename module from publisher to publish - Change all shared.* references to commons.* - Use commons.Item, commons.Feed, etc from shared library Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
module github.com/1440news/publisher
|
module github.com/1440news/publish
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// scanItems scans rows into Item structs
|
// scanItems scans rows into Item structs
|
||||||
func scanItems(rows pgx.Rows) ([]*shared.Item, error) {
|
func scanItems(rows pgx.Rows) ([]*commons.Item, error) {
|
||||||
var items []*shared.Item
|
var items []*commons.Item
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
item := &shared.Item{}
|
item := &commons.Item{}
|
||||||
var guid, title, link, description, content, author *string
|
var guid, title, link, description, content, author *string
|
||||||
var pubDate, updatedAt, publishedAt *interface{}
|
var pubDate, updatedAt, publishedAt *interface{}
|
||||||
var publishedUri *string
|
var publishedUri *string
|
||||||
@@ -32,13 +32,13 @@ func scanItems(rows pgx.Rows) ([]*shared.Item, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
item.GUID = shared.StringValue(guid)
|
item.GUID = commons.StringValue(guid)
|
||||||
item.Title = shared.StringValue(title)
|
item.Title = commons.StringValue(title)
|
||||||
item.Link = shared.StringValue(link)
|
item.Link = commons.StringValue(link)
|
||||||
item.Description = shared.StringValue(description)
|
item.Description = commons.StringValue(description)
|
||||||
item.Content = shared.StringValue(content)
|
item.Content = commons.StringValue(content)
|
||||||
item.Author = shared.StringValue(author)
|
item.Author = commons.StringValue(author)
|
||||||
item.PublishedUri = shared.StringValue(publishedUri)
|
item.PublishedUri = commons.StringValue(publishedUri)
|
||||||
|
|
||||||
if pubDate != nil {
|
if pubDate != nil {
|
||||||
if t, ok := (*pubDate).(interface{ Time() interface{} }); ok {
|
if t, ok := (*pubDate).(interface{ Time() interface{} }); ok {
|
||||||
@@ -49,9 +49,9 @@ func scanItems(rows pgx.Rows) ([]*shared.Item, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if enclosureUrl != nil && *enclosureUrl != "" {
|
if enclosureUrl != nil && *enclosureUrl != "" {
|
||||||
item.Enclosure = &shared.Enclosure{
|
item.Enclosure = &commons.Enclosure{
|
||||||
URL: *enclosureUrl,
|
URL: *enclosureUrl,
|
||||||
Type: shared.StringValue(enclosureType),
|
Type: commons.StringValue(enclosureType),
|
||||||
}
|
}
|
||||||
if enclosureLength != nil {
|
if enclosureLength != nil {
|
||||||
item.Enclosure.Length = *enclosureLength
|
item.Enclosure.Length = *enclosureLength
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func main() {
|
|||||||
fmt.Println("Starting publisher service...")
|
fmt.Println("Starting publisher service...")
|
||||||
|
|
||||||
// Open database connection
|
// Open database connection
|
||||||
db, err := shared.OpenDatabase("")
|
db, err := commons.OpenDatabase("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to connect to database: %v", err)
|
log.Fatalf("Failed to connect to database: %v", err)
|
||||||
}
|
}
|
||||||
@@ -82,14 +82,14 @@ func loadEnvFile(filename string) {
|
|||||||
|
|
||||||
// PublisherService manages publishing items to AT Protocol PDS
|
// PublisherService manages publishing items to AT Protocol PDS
|
||||||
type PublisherService struct {
|
type PublisherService struct {
|
||||||
db *shared.DB
|
db *commons.DB
|
||||||
publisher *Publisher
|
publisher *Publisher
|
||||||
pdsHost string
|
pdsHost string
|
||||||
feedPassword string
|
feedPassword string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPublisherService creates a new publisher service
|
// NewPublisherService creates a new publisher service
|
||||||
func NewPublisherService(db *shared.DB, pdsHost, feedPassword string) *PublisherService {
|
func NewPublisherService(db *commons.DB, pdsHost, feedPassword string) *PublisherService {
|
||||||
return &PublisherService{
|
return &PublisherService{
|
||||||
db: db,
|
db: db,
|
||||||
publisher: NewPublisher(pdsHost),
|
publisher: NewPublisher(pdsHost),
|
||||||
@@ -184,7 +184,7 @@ func (s *PublisherService) publishFeedItems(feedURL, account string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUnpublishedItems returns unpublished items for a feed
|
// GetUnpublishedItems returns unpublished items for a feed
|
||||||
func (s *PublisherService) GetUnpublishedItems(feedURL string, limit int) ([]*shared.Item, error) {
|
func (s *PublisherService) GetUnpublishedItems(feedURL string, limit int) ([]*commons.Item, error) {
|
||||||
rows, err := s.db.Query(`
|
rows, err := s.db.Query(`
|
||||||
SELECT feed_url, guid, title, link, description, content, author, pub_date, discovered_at, updated_at,
|
SELECT feed_url, guid, title, link, description, content, author, pub_date, discovered_at, updated_at,
|
||||||
enclosure_url, enclosure_type, enclosure_length, image_urls, tags,
|
enclosure_url, enclosure_type, enclosure_length, image_urls, tags,
|
||||||
|
|||||||
+1
-1
@@ -234,7 +234,7 @@ func formatTagsForPost(tags []string, textOffset int) (string, []BskyFacet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PublishItem posts a feed item to the PDS
|
// PublishItem posts a feed item to the PDS
|
||||||
func (p *Publisher) PublishItem(session *PDSSession, item *shared.Item) (string, error) {
|
func (p *Publisher) PublishItem(session *PDSSession, item *commons.Item) (string, error) {
|
||||||
if item.GUID == "" && item.Link == "" {
|
if item.GUID == "" && item.Link == "" {
|
||||||
return "", fmt.Errorf("item has no GUID or link, cannot publish")
|
return "", fmt.Errorf("item has no GUID or link, cannot publish")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ func (s *PublisherService) handleEnablePublish(w http.ResponseWriter, r *http.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
feedURL = shared.NormalizeURL(feedURL)
|
feedURL = commons.NormalizeURL(feedURL)
|
||||||
|
|
||||||
if account == "" {
|
if account == "" {
|
||||||
account = shared.DeriveHandleFromFeed(feedURL)
|
account = commons.DeriveHandleFromFeed(feedURL)
|
||||||
if account == "" {
|
if account == "" {
|
||||||
http.Error(w, "could not derive account handle from URL", http.StatusBadRequest)
|
http.Error(w, "could not derive account handle from URL", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@@ -82,7 +82,7 @@ func (s *PublisherService) handleDisablePublish(w http.ResponseWriter, r *http.R
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
feedURL = shared.NormalizeURL(feedURL)
|
feedURL = commons.NormalizeURL(feedURL)
|
||||||
|
|
||||||
if err := s.SetPublishStatus(feedURL, "skip", ""); err != nil {
|
if err := s.SetPublishStatus(feedURL, "skip", ""); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
@@ -110,7 +110,7 @@ func (s *PublisherService) handleSetPublishStatus(w http.ResponseWriter, r *http
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
feedURL = shared.NormalizeURL(feedURL)
|
feedURL = commons.NormalizeURL(feedURL)
|
||||||
|
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"url": feedURL,
|
"url": feedURL,
|
||||||
@@ -119,7 +119,7 @@ func (s *PublisherService) handleSetPublishStatus(w http.ResponseWriter, r *http
|
|||||||
|
|
||||||
if status == "pass" {
|
if status == "pass" {
|
||||||
if account == "" {
|
if account == "" {
|
||||||
account = shared.DeriveHandleFromFeed(feedURL)
|
account = commons.DeriveHandleFromFeed(feedURL)
|
||||||
}
|
}
|
||||||
result["account"] = account
|
result["account"] = account
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ func (s *PublisherService) handlePublishCandidates(w http.ResponseWriter, r *htt
|
|||||||
Category: f.Category,
|
Category: f.Category,
|
||||||
SourceHost: f.DomainHost,
|
SourceHost: f.DomainHost,
|
||||||
ItemCount: f.ItemCount,
|
ItemCount: f.ItemCount,
|
||||||
DerivedHandle: shared.DeriveHandleFromFeed(f.URL),
|
DerivedHandle: commons.DeriveHandleFromFeed(f.URL),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ func (s *PublisherService) handleUnpublishedItems(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
if items == nil {
|
if items == nil {
|
||||||
items = []*shared.Item{}
|
items = []*commons.Item{}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
@@ -446,7 +446,7 @@ func (s *PublisherService) handleDeriveHandle(w http.ResponseWriter, r *http.Req
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handle := shared.DeriveHandleFromFeed(feedURL)
|
handle := commons.DeriveHandleFromFeed(feedURL)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
@@ -508,19 +508,19 @@ func (s *PublisherService) handleRefreshProfiles(w http.ResponseWriter, r *http.
|
|||||||
// Database helper methods
|
// Database helper methods
|
||||||
|
|
||||||
func (s *PublisherService) SetPublishStatus(feedURL, status, account string) error {
|
func (s *PublisherService) SetPublishStatus(feedURL, status, account string) error {
|
||||||
feedURL = shared.NormalizeURL(feedURL)
|
feedURL = commons.NormalizeURL(feedURL)
|
||||||
|
|
||||||
if status == "pass" && account == "" {
|
if status == "pass" && account == "" {
|
||||||
account = shared.DeriveHandleFromFeed(feedURL)
|
account = commons.DeriveHandleFromFeed(feedURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := s.db.Exec(`
|
_, err := s.db.Exec(`
|
||||||
UPDATE feeds SET publish_status = $1, publish_account = $2 WHERE url = $3
|
UPDATE feeds SET publish_status = $1, publish_account = $2 WHERE url = $3
|
||||||
`, status, shared.NullableString(account), feedURL)
|
`, status, commons.NullableString(account), feedURL)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublisherService) GetFeedsByPublishStatus(status string) ([]*shared.Feed, error) {
|
func (s *PublisherService) GetFeedsByPublishStatus(status string) ([]*commons.Feed, error) {
|
||||||
rows, err := s.db.Query(`
|
rows, err := s.db.Query(`
|
||||||
SELECT url, type, category, title, description, language, site_url,
|
SELECT url, type, category, title, description, language, site_url,
|
||||||
discovered_at, last_checked_at, next_check_at, last_build_date,
|
discovered_at, last_checked_at, next_check_at, last_build_date,
|
||||||
@@ -541,7 +541,7 @@ func (s *PublisherService) GetFeedsByPublishStatus(status string) ([]*shared.Fee
|
|||||||
return scanFeeds(rows)
|
return scanFeeds(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublisherService) GetPublishCandidates(limit int) ([]*shared.Feed, error) {
|
func (s *PublisherService) GetPublishCandidates(limit int) ([]*commons.Feed, error) {
|
||||||
rows, err := s.db.Query(`
|
rows, err := s.db.Query(`
|
||||||
SELECT url, type, category, title, description, language, site_url,
|
SELECT url, type, category, title, description, language, site_url,
|
||||||
discovered_at, last_checked_at, next_check_at, last_build_date,
|
discovered_at, last_checked_at, next_check_at, last_build_date,
|
||||||
@@ -572,7 +572,7 @@ func (s *PublisherService) GetUnpublishedItemCount(feedURL string) (int, error)
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublisherService) GetItemByGUID(feedURL, guid string) (*shared.Item, error) {
|
func (s *PublisherService) GetItemByGUID(feedURL, guid string) (*commons.Item, error) {
|
||||||
items, err := s.db.Query(`
|
items, err := s.db.Query(`
|
||||||
SELECT feed_url, guid, title, link, description, content, author, pub_date, discovered_at, updated_at,
|
SELECT feed_url, guid, title, link, description, content, author, pub_date, discovered_at, updated_at,
|
||||||
enclosure_url, enclosure_type, enclosure_length, image_urls, tags,
|
enclosure_url, enclosure_type, enclosure_length, image_urls, tags,
|
||||||
@@ -620,11 +620,11 @@ func (s *PublisherService) RefreshAllProfiles(publisher *Publisher, feedPassword
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
displayName := shared.StringValue(title)
|
displayName := commons.StringValue(title)
|
||||||
if displayName == "" {
|
if displayName == "" {
|
||||||
displayName = account
|
displayName = account
|
||||||
}
|
}
|
||||||
desc := stripHTML(shared.StringValue(description))
|
desc := stripHTML(commons.StringValue(description))
|
||||||
if desc == "" {
|
if desc == "" {
|
||||||
desc = "News feed via 1440.news"
|
desc = "News feed via 1440.news"
|
||||||
}
|
}
|
||||||
@@ -639,9 +639,9 @@ func (s *PublisherService) RefreshAllProfiles(publisher *Publisher, feedPassword
|
|||||||
}
|
}
|
||||||
|
|
||||||
var avatar *BlobRef
|
var avatar *BlobRef
|
||||||
faviconSource := shared.StringValue(siteURL)
|
faviconSource := commons.StringValue(siteURL)
|
||||||
if faviconSource == "" {
|
if faviconSource == "" {
|
||||||
faviconSource = shared.StringValue(sourceHost)
|
faviconSource = commons.StringValue(sourceHost)
|
||||||
}
|
}
|
||||||
if faviconSource != "" {
|
if faviconSource != "" {
|
||||||
faviconData, mimeType, err := FetchFaviconBytes(faviconSource)
|
faviconData, mimeType, err := FetchFaviconBytes(faviconSource)
|
||||||
@@ -659,11 +659,11 @@ func (s *PublisherService) RefreshAllProfiles(publisher *Publisher, feedPassword
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scanFeeds helper
|
// scanFeeds helper
|
||||||
func scanFeeds(rows interface{ Next() bool; Scan(...interface{}) error; Err() error }) ([]*shared.Feed, error) {
|
func scanFeeds(rows interface{ Next() bool; Scan(...interface{}) error; Err() error }) ([]*commons.Feed, error) {
|
||||||
var feeds []*shared.Feed
|
var feeds []*commons.Feed
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
feed := &shared.Feed{}
|
feed := &commons.Feed{}
|
||||||
var feedType, category, title, description, language, siteURL *string
|
var feedType, category, title, description, language, siteURL *string
|
||||||
var lastCheckedAt, nextCheckAt, lastBuildDate *interface{}
|
var lastCheckedAt, nextCheckAt, lastBuildDate *interface{}
|
||||||
var etag, lastModified, lastError, sourceURL, domainTLD *string
|
var etag, lastModified, lastError, sourceURL, domainTLD *string
|
||||||
@@ -685,19 +685,19 @@ func scanFeeds(rows interface{ Next() bool; Scan(...interface{}) error; Err() er
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
feed.Type = shared.StringValue(feedType)
|
feed.Type = commons.StringValue(feedType)
|
||||||
feed.Category = shared.StringValue(category)
|
feed.Category = commons.StringValue(category)
|
||||||
feed.Title = shared.StringValue(title)
|
feed.Title = commons.StringValue(title)
|
||||||
feed.Description = shared.StringValue(description)
|
feed.Description = commons.StringValue(description)
|
||||||
feed.Language = shared.StringValue(language)
|
feed.Language = commons.StringValue(language)
|
||||||
feed.SiteURL = shared.StringValue(siteURL)
|
feed.SiteURL = commons.StringValue(siteURL)
|
||||||
feed.ETag = shared.StringValue(etag)
|
feed.ETag = commons.StringValue(etag)
|
||||||
feed.LastModified = shared.StringValue(lastModified)
|
feed.LastModified = commons.StringValue(lastModified)
|
||||||
feed.LastError = shared.StringValue(lastError)
|
feed.LastError = commons.StringValue(lastError)
|
||||||
feed.SourceURL = shared.StringValue(sourceURL)
|
feed.SourceURL = commons.StringValue(sourceURL)
|
||||||
feed.DomainTLD = shared.StringValue(domainTLD)
|
feed.DomainTLD = commons.StringValue(domainTLD)
|
||||||
feed.PublishStatus = shared.StringValue(publishStatus)
|
feed.PublishStatus = commons.StringValue(publishStatus)
|
||||||
feed.PublishAccount = shared.StringValue(publishAccount)
|
feed.PublishAccount = commons.StringValue(publishAccount)
|
||||||
|
|
||||||
feeds = append(feeds, feed)
|
feeds = append(feeds, feed)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user