138 lines
4.8 KiB
Go
138 lines
4.8 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Bot represents a Nostr posting bot
|
|
type Bot struct {
|
|
ID int64 `db:"id" json:"id"`
|
|
Pubkey string `db:"pubkey" json:"pubkey"`
|
|
EncryptedPrivkey string `db:"encrypted_privkey" json:"encrypted_privkey,omitempty"`
|
|
Name string `db:"name" json:"name"`
|
|
DisplayName string `db:"display_name" json:"display_name"`
|
|
Bio string `db:"bio" json:"bio"`
|
|
Nip05 string `db:"nip05" json:"nip05"`
|
|
ZapAddress string `db:"zap_address" json:"zap_address"`
|
|
ProfilePicture string `db:"profile_picture" json:"profile_picture"`
|
|
Banner string `db:"banner" json:"banner"`
|
|
Website sql.NullString `db:"website" json:"website,omitempty"` // Changed to sql.NullString to handle NULL values
|
|
// Custom JSON marshaling is handled in MarshalJSON/UnmarshalJSON methods
|
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
|
OwnerPubkey string `db:"owner_pubkey" json:"owner_pubkey"`
|
|
|
|
// The following are not stored in the database
|
|
PostConfig *PostConfig `json:"post_config,omitempty"`
|
|
MediaConfig *MediaConfig `json:"media_config,omitempty"`
|
|
Relays []*Relay `json:"relays,omitempty"`
|
|
}
|
|
|
|
// PostConfig represents the posting configuration for a bot
|
|
type PostConfig struct {
|
|
ID int64 `db:"id" json:"id"`
|
|
BotID int64 `db:"bot_id" json:"-"`
|
|
Hashtags string `db:"hashtags" json:"hashtags"` // JSON array stored as string
|
|
IntervalMinutes int `db:"interval_minutes" json:"interval_minutes"`
|
|
PostTemplate string `db:"post_template" json:"post_template"`
|
|
Enabled bool `db:"enabled" json:"enabled"`
|
|
}
|
|
|
|
// MediaConfig represents the media upload configuration for a bot
|
|
type MediaConfig struct {
|
|
ID int64 `db:"id" json:"id"`
|
|
BotID int64 `db:"bot_id" json:"-"`
|
|
PrimaryService string `db:"primary_service" json:"primary_service"` // "nip94" or "blossom"
|
|
FallbackService string `db:"fallback_service" json:"fallback_service"`
|
|
Nip94ServerURL string `db:"nip94_server_url" json:"nip94_server_url"`
|
|
BlossomServerURL string `db:"blossom_server_url" json:"blossom_server_url"`
|
|
}
|
|
|
|
// Relay represents a Nostr relay configuration
|
|
type Relay struct {
|
|
ID int64 `db:"id" json:"id"`
|
|
BotID int64 `db:"bot_id" json:"-"`
|
|
URL string `db:"url" json:"url"`
|
|
Read bool `db:"read" json:"read"`
|
|
Write bool `db:"write" json:"write"`
|
|
OwnerPubkey string `db:"owner_pubkey" json:"owner_pubkey,omitempty"` // Add this field
|
|
}
|
|
|
|
// Post represents a post made by the bot
|
|
type Post struct {
|
|
ID int64 `db:"id" json:"id"`
|
|
BotID int64 `db:"bot_id" json:"bot_id"`
|
|
ContentFilename string `db:"content_filename" json:"content_filename"`
|
|
MediaURL string `db:"media_url" json:"media_url"`
|
|
EventID string `db:"event_id" json:"event_id"`
|
|
Status string `db:"status" json:"status"` // "pending", "posted", "failed"
|
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
|
Error string `db:"error" json:"error,omitempty"`
|
|
}
|
|
|
|
// MarshalJSON handles custom JSON marshaling for Bot, especially for sql.NullString fields
|
|
func (b Bot) MarshalJSON() ([]byte, error) {
|
|
type Alias Bot // Create an alias to avoid infinite recursion
|
|
|
|
// Create a copy of the bot to modify for JSON
|
|
bot := &struct {
|
|
Website interface{} `json:"website,omitempty"`
|
|
*Alias
|
|
}{
|
|
Alias: (*Alias)(&b),
|
|
}
|
|
|
|
// Handle the sql.NullString field specifically
|
|
if b.Website.Valid {
|
|
bot.Website = b.Website.String
|
|
} else {
|
|
bot.Website = nil
|
|
}
|
|
|
|
return json.Marshal(bot)
|
|
}
|
|
|
|
// UnmarshalJSON handles custom JSON unmarshaling for Bot, especially for sql.NullString fields
|
|
func (b *Bot) UnmarshalJSON(data []byte) error {
|
|
type Alias Bot // Create an alias to avoid infinite recursion
|
|
|
|
// Create a proxy structure with website as interface{}
|
|
aux := &struct {
|
|
Website interface{} `json:"website,omitempty"`
|
|
*Alias
|
|
}{
|
|
Alias: (*Alias)(b),
|
|
}
|
|
|
|
if err := json.Unmarshal(data, &aux); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Handle possible types for the website field
|
|
if aux.Website == nil {
|
|
b.Website = sql.NullString{Valid: false}
|
|
} else {
|
|
switch v := aux.Website.(type) {
|
|
case string:
|
|
b.Website = sql.NullString{String: v, Valid: true}
|
|
case map[string]interface{}:
|
|
// Handle specific JSON format for sql.NullString
|
|
if str, ok := v["String"].(string); ok {
|
|
valid := true
|
|
if v, ok := v["Valid"].(bool); ok {
|
|
valid = v
|
|
}
|
|
b.Website = sql.NullString{String: str, Valid: valid}
|
|
}
|
|
case nil:
|
|
b.Website = sql.NullString{Valid: false}
|
|
default:
|
|
return fmt.Errorf("unsupported type for Website: %T", v)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|