You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

322 lines
8.2 KiB

package toot
import (
"fmt"
"time"
"errors"
"strings"
"strconv"
//"encoding/json"
//"net/url"
)
func (s TootStatus) AnswerTo ( status *TootStatus ) ( *TootStatus, error ) {
status.InReplyToId = s.Id
return status.PostStatus ( nil )
}
func GetScheduled () ( []TootScheduledStatus, error ) {
var s []TootScheduledStatus
err := lc.SimpleRequest ( "scheduled_statuses/", "GET", &s )
return s, err
}
func GetStatus( id string ) ( *TootStatus, error ) {
if len(id) == 0 {
return nil, errors.New ( "Need a valid Status ID" )
}
var s TootStatus
err := lc.SimpleRequest ( "statuses/"+id, "GET", &s )
return &s, err
}
func (s* TootStatus) GetUpdate() error {
st, err := GetStatus ( s.Id )
if err != nil {
return err
}
s = st
return nil
}
func (s TootStatus) Context() ( *TootContext, error ) {
if len(s.Id) == 0 {
return nil, errors.New ( "Need a valid Status ID" )
}
resp, err := lc.Get ( "statuses/"+s.Id+"/context" )
if err != nil {
return nil, err
}
var ctx TootContext
err = lc.DecodeResponse ( resp, &ctx )
if err != nil {
return nil, err
}
return &ctx, nil
}
/*
func (s TootStatus) Card() ( *TootCard, error ) {
if len(s.Id) == 0 {
return nil, errors.New ( "Need a valid Status ID" )
}
resp, err := lc.Get ( "statuses/"+s.Id+"/card" )
if err != nil {
return nil, err
}
var card TootCard
err = lc.DecodeResponse ( resp, &card )
if err != nil {
return nil, err
}
return card, nil
}*/
func (s *TootStatus) DeleteStatus() error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id, "DELETE", nil )
s = &TootStatus{}
return err
}
func (s TootStatus) RebloggedBy() ( []TootAccount, error ) {
if len(s.Id) == 0 {
return nil, errors.New ( "Need a valid Status ID" )
}
var accs []TootAccount
err := lc.SimpleRequest ( "statuses/"+s.Id+"/reblogged_by", "GET", &accs )
return accs, err
}
func (s TootStatus) FavouritedBy() ( []TootAccount, error ) {
if len(s.Id) == 0 {
return nil, errors.New ( "Need a valid Status ID" )
}
var accs []TootAccount
err := lc.SimpleRequest ( "statuses/"+s.Id+"/favourited_by", "GET", &accs )
return accs, err
}
func (s TootStatus ) GetIdempotencyKey () string {
return "DiesIstEinBeispielIdempotencyKey"
}
func (s *TootStatus) PostReblog () error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id+"/reblog", "POST", nil )
return err
}
func (s *TootStatus) PostUnreblog () error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id+"/unreblog", "POST", nil )
return err
}
func (s *TootStatus) PostFavourite () error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id+"/favourite", "POST", nil )
return err
}
func (s *TootStatus) PostUnfavourite () error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id+"/unfavourite", "POST", nil )
return err
}
func (s *TootStatus) PostPin () error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id+"/pin", "POST", nil )
return err
}
func (s *TootStatus) PostUnpin () error {
if len(s.Id) == 0 {
return errors.New ( "Need a valid Status ID" )
}
err := lc.SimpleRequest ( "statuses/"+s.Id+"/unpin", "POST", nil )
return err
}
func (s *TootStatus) AddPoll ( options []string, expiresAt time.Time, multiple bool, hideTotals bool ) {
var poll TootPoll = TootPoll {
ExpiresAt : expiresAt,
Multiple : multiple,
HideTotals : hideTotals,
}
for _, v := range options {
p := TootPollOptions { Title: v, VotesCount: 0 }
poll.Options = append ( poll.Options, p )
}
s.Poll = &poll;
}
func (s *TootStatus) SanityCheck () error {
strings.ReplaceAll(s.Content, "\"", "\\\"")
if len(s.Content) >= 500 {
return errors.New ("Status is too long")
}
if s.Content == "" && s.Poll != nil {
return errors.New ("Poll needs a Status-Text")
}
if s.Poll != nil {
if len(s.Poll.Options) > 4 {
return errors.New ("Only 4 poll options allowed")
}
for _, v := range s.Poll.Options {
strings.ReplaceAll(v.Title, "\"", "\\\"")
if len(v.Title) >= 25 {
return errors.New("Polly options can only be 25 characters long")
}
}
}
if s.Visibility != "public" && s.Visibility != "unlisted" && s.Visibility != "private" && s.Visibility != "direct" {
s.Visibility = "public"
}
return nil
}
func (s *TootStatus) DeleteAttachments () {
for range s.MediaAttachments {
// This would be a delete, but apparently mastodon does not allow deletes...
}
s.MediaAttachments = []TootAttachment{}
}
type Media struct {
Filename string
Description string
FocalX float64
FocalY float64
}
func (s *TootStatus) AddAttachments ( paths []Media ) error {
for _, p := range paths {
if p.Filename == "" {
continue
}
var a TootAttachment
a.SetFilename ( p.Filename )
a.SetDescription ( p.Description )
ta, err := a.Post ()
if err != nil {
s.DeleteAttachments ()
return err
}
s.addAttachment ( *ta )
}
return nil
}
func (s *TootStatus) addAttachment ( ta TootAttachment ) {
if len(s.MediaAttachments) < 4 {
s.MediaAttachments = append ( s.MediaAttachments, ta )
}
}
func (s TootStatus) PostStatus( scheduled *time.Time ) ( *TootStatus, error ) {
if s.Content == "" && len(s.MediaAttachments) == 0 {
return nil, errors.New("Content is empty")
}
err := s.SanityCheck()
if err != nil {
return nil, err
}
var data strings.Builder
data.WriteString("\"status\": \""+s.Content+"\"")
if s.SpoilerText != "" {
data.WriteString(", \"spoiler_text\": \"" + s.SpoilerText +"\"")
}
if s.InReplyToId != "" {
data.WriteString(", \"in_reply_to_id\": \"" + s.InReplyToId +"\"")
}
if s.Sensitive {
data.WriteString(", \"sensitive\": true")
}
if s.Language != "" {
data.WriteString(", \"language\": \"" + s.Language +"\"")
}
if scheduled != nil {
txt, err := scheduled.MarshalText()
if err != nil {
return nil, err
}
data.WriteString(", \"scheduled_at\": \"" + string(txt) +"\"")
}
if len(s.MediaAttachments) > 0 {
var media strings.Builder
for i,v := range s.MediaAttachments {
if i > 0 {
media.WriteString ( "," )
}
media.WriteString ( "\"" + v.Id + "\"" )
}
data.WriteString ( ", \"media_ids\": [ "+ media.String() +" ]" )
}
if s.Poll != nil {
var options strings.Builder
var poll strings.Builder
for i, v := range s.Poll.Options {
if i > 0 {
options.WriteString ( "," )
}
options.WriteString ( "\"" + v.Title + "\"" )
}
poll.WriteString ("\"options\": [ " + options.String() + "]")
poll.WriteString (", \"expires_in\": " + strconv.Itoa(int(s.Poll.ExpiresAt.Sub( time.Now() ).Seconds())) )
if s.Poll.Multiple {
poll.WriteString (", \"multiple\": true")
}
if s.Poll.HideTotals {
poll.WriteString (", \"hide_totals\": true")
}
data.WriteString (", \"poll\" : { " + poll.String() + " }")
}
data.WriteString (", \"visibility\": \"" + s.Visibility +"\"")
fmt.Println ("JSON: ", "{" + data.String() + "}")
resp, err := lc.PostJSON ( "statuses", "{" + data.String() + "}")
if err != nil {
return nil, err
}
var stat TootStatus
err = lc.DecodeResponse ( resp, &stat )
if err != nil {
return nil, err
}
return &stat, nil
}