removed all "paid" features - no more stars, gifts, or grams
This commit is contained in:
parent
d4451d753c
commit
21d8e91756
165 changed files with 318 additions and 40948 deletions
|
|
@ -150,32 +150,10 @@ func (s *ChannelStore) ToggleSuggestedPostApproval(ctx context.Context, req doma
|
|||
return domain.ToggleSuggestedPostApprovalResult{}, err
|
||||
}
|
||||
} else {
|
||||
stars, ton, enough, err := reserveSuggestedPostPaymentTx(ctx, tx, original.SavedPeer.ID, parent.ID, price, req.Date)
|
||||
if err != nil {
|
||||
return domain.ToggleSuggestedPostApprovalResult{}, err
|
||||
}
|
||||
result.PayerStarsBalance, result.PayerTONBalance = stars, ton
|
||||
if !enough {
|
||||
if found {
|
||||
result, err = s.loadSuggestedPostResultTx(ctx, tx, existing, true)
|
||||
if err != nil {
|
||||
return domain.ToggleSuggestedPostApprovalResult{}, err
|
||||
}
|
||||
result.PayerStarsBalance, result.PayerTONBalance = stars, ton
|
||||
} else {
|
||||
result.ServiceMessage, result.ServiceEvent, err = s.insertSuggestedPostServiceTx(ctx, tx, mono, parent, req.UserID, fromSubscriber && manager.CanManageDirectMessages(), original.SavedPeer, original.ID, req.Date, domain.ChannelMessageAction{
|
||||
Type: domain.ChannelActionSuggestedPostApproval, SuggestedPostBalanceTooLow: true,
|
||||
SuggestedPostScheduleDate: scheduleDate, SuggestedPostPrice: price,
|
||||
})
|
||||
if err != nil {
|
||||
return domain.ToggleSuggestedPostApprovalResult{}, err
|
||||
}
|
||||
result.State = domain.SuggestedPostStateBalanceLow
|
||||
if err := upsertSuggestedPostApprovalTx(ctx, tx, persistedSuggestedPostApproval{monoforumID: mono.ID, messageID: original.ID, parentID: parent.ID, actorID: req.UserID, payerID: original.SavedPeer.ID, state: result.State, price: price, scheduleDate: scheduleDate, approvalServiceID: result.ServiceMessage.ID}, req.Date); err != nil {
|
||||
return domain.ToggleSuggestedPostApprovalResult{}, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// telesrv has no Stars economy: a suggested post is approved for free
|
||||
// regardless of any price attached to it, so the balance-check/collect
|
||||
// step and its "balance too low" retry state are skipped entirely.
|
||||
{
|
||||
effectivePublishDate := scheduleDate
|
||||
original.SuggestedPost.Accepted, original.SuggestedPost.Rejected, original.SuggestedPost.ScheduleDate = true, false, effectivePublishDate
|
||||
original, result.OriginalEvent, err = s.persistSuggestedPostEditTx(ctx, tx, original, req.UserID, req.Date)
|
||||
|
|
@ -195,12 +173,10 @@ func (s *ChannelStore) ToggleSuggestedPostApproval(ctx context.Context, req doma
|
|||
}
|
||||
result.Published = &published
|
||||
record.publishedMessageID = published.Message.ID
|
||||
if price == nil {
|
||||
record.state = domain.SuggestedPostStateCompleted
|
||||
} else {
|
||||
record.state = domain.SuggestedPostStatePublished
|
||||
record.settlementDue = req.Date + suggestedPostSettlementAge
|
||||
}
|
||||
// telesrv has no Stars economy: there is nothing to settle after
|
||||
// publish (no charge was ever collected), so a published post
|
||||
// goes straight to Completed regardless of any attached price.
|
||||
record.state = domain.SuggestedPostStateCompleted
|
||||
}
|
||||
result.State = record.state
|
||||
if err := upsertSuggestedPostApprovalTx(ctx, tx, record, req.Date); err != nil {
|
||||
|
|
@ -301,56 +277,6 @@ func (s *ChannelStore) publishSuggestedPostTx(ctx context.Context, tx pgx.Tx, pa
|
|||
return domain.SendChannelMessageResult{Channel: parent, Message: msg, Event: event, Recipients: recipients}, nil
|
||||
}
|
||||
|
||||
func reserveSuggestedPostPaymentTx(ctx context.Context, tx pgx.Tx, payerID, parentID int64, price *domain.SuggestedPostPrice, date int) (*domain.StarsBalance, *int64, bool, error) {
|
||||
if price == nil {
|
||||
return nil, nil, true, nil
|
||||
}
|
||||
switch price.Kind {
|
||||
case domain.SuggestedPostPriceStars:
|
||||
if price.Nanos != 0 || price.Amount <= 0 {
|
||||
return nil, nil, false, domain.ErrSuggestedPostInvalid
|
||||
}
|
||||
balance := domain.StarsBalance{UserID: payerID}
|
||||
err := tx.QueryRow(ctx, `SELECT balance,granted FROM stars_balances WHERE user_id=$1 FOR UPDATE`, payerID).Scan(&balance.Balance, &balance.Granted)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return &balance, nil, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
if balance.Balance < price.Amount {
|
||||
return &balance, nil, false, nil
|
||||
}
|
||||
if err := tx.QueryRow(ctx, `UPDATE stars_balances SET balance=balance-$2,updated_at=now() WHERE user_id=$1 RETURNING balance`, payerID, price.Amount).Scan(&balance.Balance); err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
if err := insertStarsTxn(ctx, tx, payerID, -price.Amount, domain.StarsReasonSuggestedPost, domain.Peer{Type: domain.PeerTypeChannel, ID: parentID}, date, "Suggested post escrow", ""); err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
return &balance, nil, true, nil
|
||||
case domain.SuggestedPostPriceTON:
|
||||
var balance int64
|
||||
err := tx.QueryRow(ctx, `SELECT balance_nanoton FROM ton_balances WHERE user_id=$1 FOR UPDATE`, payerID).Scan(&balance)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, &balance, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
if balance < price.Amount {
|
||||
return nil, &balance, false, nil
|
||||
}
|
||||
if err := tx.QueryRow(ctx, `UPDATE ton_balances SET balance_nanoton=balance_nanoton-$2,updated_at=now() WHERE user_id=$1 RETURNING balance_nanoton`, payerID, price.Amount).Scan(&balance); err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `INSERT INTO ton_transactions(user_id,amount_nanoton,reason,peer_type,peer_id,date) VALUES($1,$2,$3,'channel',$4,$5)`, payerID, -price.Amount, string(domain.StarsReasonSuggestedPost), parentID, date); err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
return nil, &balance, true, nil
|
||||
default:
|
||||
return nil, nil, false, domain.ErrSuggestedPostInvalid
|
||||
}
|
||||
}
|
||||
|
||||
func monoforumManagerRecipientsTx(ctx context.Context, tx pgx.Tx, parentID, subscriberID int64) ([]int64, error) {
|
||||
rows, err := tx.Query(ctx, `SELECT user_id FROM channel_members WHERE channel_id=$1 AND status='active' AND (role='creator' OR (role='admin' AND COALESCE((admin_rights->>'ManageDirectMessages')::boolean,false))) ORDER BY user_id`, parentID)
|
||||
|
|
@ -560,19 +486,12 @@ func (s *ChannelStore) processSuggestedPostLifecycleOne(ctx context.Context, mon
|
|||
}
|
||||
result := domain.ToggleSuggestedPostApprovalResult{Monoforum: mono, Parent: parent, SavedPeer: domain.Peer{Type: domain.PeerTypeUser, ID: row.payerID}, State: row.state, Recipients: recipients}
|
||||
changed := false
|
||||
// telesrv has no Stars economy: nothing was ever charged, so a deleted
|
||||
// scheduled post is simply dropped (Refunded is the closest existing
|
||||
// terminal state, reused here so downstream event handling stays uniform)
|
||||
// and a published post is Completed immediately -- there is no settlement
|
||||
// window and no refund path to run.
|
||||
if row.state == domain.SuggestedPostStateScheduled && original.Deleted {
|
||||
if row.price != nil {
|
||||
stars, ton, err := refundSuggestedPostPaymentTx(ctx, tx, row.payerID, row.parentID, row.price, now)
|
||||
if err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
result.PayerStarsBalance, result.PayerTONBalance = stars, ton
|
||||
service, event, err := s.insertSuggestedPostServiceTx(ctx, tx, mono, parent, row.actorID, true, row.savedPeer(), row.messageID, now, domain.ChannelMessageAction{Type: domain.ChannelActionSuggestedPostRefund})
|
||||
if err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
result.ServiceMessage, result.ServiceEvent, row.finalServiceID = service, event, service.ID
|
||||
}
|
||||
row.state, result.State, changed = domain.SuggestedPostStateRefunded, domain.SuggestedPostStateRefunded, true
|
||||
}
|
||||
if row.state == domain.SuggestedPostStateScheduled && row.scheduleDate <= now {
|
||||
|
|
@ -582,47 +501,10 @@ func (s *ChannelStore) processSuggestedPostLifecycleOne(ctx context.Context, mon
|
|||
}
|
||||
result.Published = &published
|
||||
row.publishedMessageID = published.Message.ID
|
||||
if row.price == nil {
|
||||
row.state = domain.SuggestedPostStateCompleted
|
||||
} else {
|
||||
row.state = domain.SuggestedPostStatePublished
|
||||
row.settlementDue = now + suggestedPostSettlementAge
|
||||
}
|
||||
row.state = domain.SuggestedPostStateCompleted
|
||||
result.State = row.state
|
||||
changed = true
|
||||
}
|
||||
if row.state == domain.SuggestedPostStatePublished {
|
||||
var deleted bool
|
||||
var deleteDate int
|
||||
if err := tx.QueryRow(ctx, `SELECT deleted,delete_date FROM channel_messages WHERE channel_id=$1 AND id=$2 FOR SHARE`, row.parentID, row.publishedMessageID).Scan(&deleted, &deleteDate); err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
if deleted && (deleteDate == 0 || deleteDate < row.settlementDue) {
|
||||
stars, ton, err := refundSuggestedPostPaymentTx(ctx, tx, row.payerID, row.parentID, row.price, now)
|
||||
if err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
result.PayerStarsBalance, result.PayerTONBalance = stars, ton
|
||||
service, event, err := s.insertSuggestedPostServiceTx(ctx, tx, mono, parent, row.actorID, true, row.savedPeer(), row.messageID, now, domain.ChannelMessageAction{Type: domain.ChannelActionSuggestedPostRefund})
|
||||
if err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
result.ServiceMessage, result.ServiceEvent = service, event
|
||||
row.state, row.finalServiceID, result.State = domain.SuggestedPostStateRefunded, service.ID, domain.SuggestedPostStateRefunded
|
||||
changed = true
|
||||
} else if row.settlementDue <= now {
|
||||
if err := settleSuggestedPostPaymentTx(ctx, tx, row.actorID, row.payerID, row.parentID, row.price, now); err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
service, event, err := s.insertSuggestedPostServiceTx(ctx, tx, mono, parent, row.actorID, true, row.savedPeer(), row.messageID, now, domain.ChannelMessageAction{Type: domain.ChannelActionSuggestedPostSuccess, SuggestedPostPrice: cloneSuggestedPricePG(row.price)})
|
||||
if err != nil {
|
||||
return result, false, err
|
||||
}
|
||||
result.ServiceMessage, result.ServiceEvent = service, event
|
||||
row.state, row.finalServiceID, result.State = domain.SuggestedPostStateCompleted, service.ID, domain.SuggestedPostStateCompleted
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return result, false, err
|
||||
|
|
@ -652,56 +534,4 @@ func (r persistedSuggestedPostApproval) savedPeer() domain.Peer {
|
|||
return domain.Peer{Type: domain.PeerTypeUser, ID: r.payerID}
|
||||
}
|
||||
|
||||
func refundSuggestedPostPaymentTx(ctx context.Context, tx pgx.Tx, payerID, parentID int64, price *domain.SuggestedPostPrice, date int) (*domain.StarsBalance, *int64, error) {
|
||||
if price == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
switch price.Kind {
|
||||
case domain.SuggestedPostPriceStars:
|
||||
balance := domain.StarsBalance{UserID: payerID, Granted: true}
|
||||
if err := tx.QueryRow(ctx, `INSERT INTO stars_balances(user_id,balance,granted) VALUES($1,$2,true) ON CONFLICT(user_id) DO UPDATE SET balance=stars_balances.balance+EXCLUDED.balance,updated_at=now() RETURNING balance,granted`, payerID, price.Amount).Scan(&balance.Balance, &balance.Granted); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := insertStarsTxn(ctx, tx, payerID, price.Amount, domain.StarsReasonSuggestedPost, domain.Peer{Type: domain.PeerTypeChannel, ID: parentID}, date, "Suggested post refund", ""); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &balance, nil, nil
|
||||
case domain.SuggestedPostPriceTON:
|
||||
var balance int64
|
||||
if err := tx.QueryRow(ctx, `INSERT INTO ton_balances(user_id,balance_nanoton,granted) VALUES($1,$2,true) ON CONFLICT(user_id) DO UPDATE SET balance_nanoton=ton_balances.balance_nanoton+EXCLUDED.balance_nanoton,updated_at=now() RETURNING balance_nanoton`, payerID, price.Amount).Scan(&balance); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `INSERT INTO ton_transactions(user_id,amount_nanoton,reason,peer_type,peer_id,date) VALUES($1,$2,$3,'channel',$4,$5)`, payerID, price.Amount, string(domain.StarsReasonSuggestedPost), parentID, date); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return nil, &balance, nil
|
||||
default:
|
||||
return nil, nil, domain.ErrSuggestedPostInvalid
|
||||
}
|
||||
}
|
||||
|
||||
func settleSuggestedPostPaymentTx(ctx context.Context, tx pgx.Tx, actorID, payerID, parentID int64, price *domain.SuggestedPostPrice, date int) error {
|
||||
if price == nil {
|
||||
return nil
|
||||
}
|
||||
credit := price.Amount * paidMessageChannelCommissionPermille / 1000
|
||||
if credit <= 0 {
|
||||
return nil
|
||||
}
|
||||
switch price.Kind {
|
||||
case domain.SuggestedPostPriceStars:
|
||||
if _, err := tx.Exec(ctx, `INSERT INTO channel_stars_balances(channel_id,balance) VALUES($1,$2) ON CONFLICT(channel_id) DO UPDATE SET balance=channel_stars_balances.balance+EXCLUDED.balance,updated_at=now()`, parentID, credit); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `INSERT INTO channel_stars_transactions(channel_id,actor_user_id,amount,reason,peer_type,peer_id,date) VALUES($1,$2,$3,$4,'user',$5,$6)`, parentID, actorID, credit, string(domain.StarsReasonSuggestedPost), payerID, date)
|
||||
return err
|
||||
case domain.SuggestedPostPriceTON:
|
||||
if _, err := tx.Exec(ctx, `INSERT INTO channel_ton_balances(channel_id,balance_nanoton) VALUES($1,$2) ON CONFLICT(channel_id) DO UPDATE SET balance_nanoton=channel_ton_balances.balance_nanoton+EXCLUDED.balance_nanoton,updated_at=now()`, parentID, credit); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Exec(ctx, `INSERT INTO channel_ton_transactions(channel_id,actor_user_id,amount_nanoton,reason,peer_type,peer_id,date) VALUES($1,$2,$3,$4,'user',$5,$6)`, parentID, actorID, credit, string(domain.StarsReasonSuggestedPost), payerID, date)
|
||||
return err
|
||||
default:
|
||||
return domain.ErrSuggestedPostInvalid
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue