2022-08-02 12:56:26 +00:00
|
|
|
package sociallinkssettings
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/status-im/status-go/protocol/identity"
|
|
|
|
)
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
const (
|
|
|
|
MaxNumOfSocialLinks = 20
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2023-06-06 13:37:24 +00:00
|
|
|
ErrNilSocialLinkProvided = errors.New("social links, nil object provided")
|
|
|
|
ErrOlderSocialLinksProvided = errors.New("older social links provided")
|
2023-06-05 11:10:26 +00:00
|
|
|
)
|
|
|
|
|
2022-08-02 12:56:26 +00:00
|
|
|
type SocialLinksSettings struct {
|
|
|
|
db *sql.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSocialLinksSettings(db *sql.DB) *SocialLinksSettings {
|
|
|
|
return &SocialLinksSettings{
|
|
|
|
db: db,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
func (s *SocialLinksSettings) getSocialLinksClock(tx *sql.Tx) (result uint64, err error) {
|
|
|
|
query := "SELECT social_links FROM settings_sync_clock WHERE synthetic_id = 'id'"
|
|
|
|
if tx == nil {
|
|
|
|
err = s.db.QueryRow(query).Scan(&result)
|
|
|
|
} else {
|
|
|
|
err = tx.QueryRow(query).Scan(&result)
|
2023-04-19 22:59:09 +00:00
|
|
|
}
|
2023-06-05 11:10:26 +00:00
|
|
|
return result, err
|
2023-04-19 22:59:09 +00:00
|
|
|
}
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
func (s *SocialLinksSettings) getSocialLinks(tx *sql.Tx) (identity.SocialLinks, error) {
|
|
|
|
var (
|
|
|
|
rows *sql.Rows
|
|
|
|
err error
|
|
|
|
)
|
2023-06-05 14:28:10 +00:00
|
|
|
query := "SELECT text, url FROM profile_social_links ORDER BY position ASC"
|
2023-06-05 11:10:26 +00:00
|
|
|
|
|
|
|
if tx == nil {
|
|
|
|
rows, err = s.db.Query(query)
|
|
|
|
} else {
|
|
|
|
rows, err = tx.Query(query)
|
|
|
|
}
|
2022-08-02 12:56:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
var socialLinks identity.SocialLinks
|
2022-08-02 12:56:26 +00:00
|
|
|
for rows.Next() {
|
2023-06-05 11:10:26 +00:00
|
|
|
socialLink := &identity.SocialLink{}
|
|
|
|
err := rows.Scan(&socialLink.Text, &socialLink.URL)
|
2022-08-02 12:56:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-06-05 11:10:26 +00:00
|
|
|
socialLinks = append(socialLinks, socialLink)
|
|
|
|
}
|
2022-08-02 12:56:26 +00:00
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
err = rows.Err()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2022-08-02 12:56:26 +00:00
|
|
|
}
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
return socialLinks, nil
|
2022-08-02 12:56:26 +00:00
|
|
|
}
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
func (s *SocialLinksSettings) GetSocialLinks() (identity.SocialLinks, error) {
|
|
|
|
return s.getSocialLinks(nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SocialLinksSettings) GetSocialLinksClock() (result uint64, err error) {
|
|
|
|
return s.getSocialLinksClock(nil)
|
|
|
|
}
|
2022-08-02 12:56:26 +00:00
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
func (s *SocialLinksSettings) AddOrReplaceSocialLinksIfNewer(links identity.SocialLinks, clock uint64) error {
|
2022-08-02 12:56:26 +00:00
|
|
|
tx, err := s.db.BeginTx(context.Background(), &sql.TxOptions{})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer func() {
|
|
|
|
if err == nil {
|
|
|
|
err = tx.Commit()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
_ = tx.Rollback()
|
|
|
|
}()
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
dbClock, err := s.getSocialLinksClock(tx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if dbClock > clock {
|
2023-06-06 13:37:24 +00:00
|
|
|
return ErrOlderSocialLinksProvided
|
2023-06-05 11:10:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dbLinks, err := s.getSocialLinks(tx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(dbLinks) > 0 {
|
|
|
|
_, err = tx.Exec("DELETE from profile_social_links")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2022-08-02 12:56:26 +00:00
|
|
|
|
2023-06-05 14:28:10 +00:00
|
|
|
stmt, err := tx.Prepare("INSERT INTO profile_social_links (text, url, position) VALUES (?, ?, ?)")
|
2022-08-02 12:56:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer stmt.Close()
|
|
|
|
|
2023-06-05 14:28:10 +00:00
|
|
|
for position, link := range links {
|
2023-06-05 11:10:26 +00:00
|
|
|
if link == nil {
|
|
|
|
return ErrNilSocialLinkProvided
|
|
|
|
}
|
2022-08-02 12:56:26 +00:00
|
|
|
_, err = stmt.Exec(
|
|
|
|
link.Text,
|
|
|
|
link.URL,
|
2023-06-05 14:28:10 +00:00
|
|
|
position,
|
2022-08-02 12:56:26 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
stmt, err = tx.Prepare("UPDATE settings_sync_clock SET social_links = ? WHERE synthetic_id = 'id'")
|
2023-04-19 22:59:09 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-05 11:10:26 +00:00
|
|
|
_, err = stmt.Exec(clock)
|
|
|
|
return err
|
2023-04-19 22:59:09 +00:00
|
|
|
}
|