ref: e2bb9b699ab1ad34feff0934975a0597f8c74a9f
parent: 7d674e742a31262b0366192c761ade0cd79d59dc
author: penny <penny@limitedideas.org>
date: Thu Nov 13 13:18:37 EST 2025
gofmt pass + /cat shows the client that posted the status if specified
--- a/commands.go
+++ b/commands.go
@@ -1,15 +1,15 @@
package main
import (
+ "context"
"fmt"
"runtime/debug"
+ "strconv"
"strings"
"time"
- "context"
- "strconv"
-
- "github.com/k3a/html2text"
+
mastodon "codeberg.org/penny64/hellclient-go-mastodon"
+ "github.com/k3a/html2text"
)
func processInput(input string, commands []string) (command string, arguments string, found bool) {@@ -167,7 +167,7 @@
return "", fmt.Errorf("Command %s not found.\n", data.command)}
flags := loader.cmdmap[data.command].flags()
-
+
// Command needs us to resolve @user@domain targets as indexes
if flags&acc_resolve != 0 {data.account = data.lookupAccount(loader)
@@ -179,7 +179,7 @@
}
}
}
-
+
// Command wants us to load the user's most recently made status
if flags&want_recent != 0 && !data.found_index { if hc.recentpost != nil {@@ -205,7 +205,7 @@
data.targeturl = hc.homeref.urlmap[data.index][urlindex-1]
}
}
-
+
err = data.checkReqs(loader.cmdmap[data.command].flags())
if err != nil {return "", err
@@ -283,11 +283,10 @@
found_index bool
dot_index bool
index string
- targeturl string
+ targeturl string
templater *templateRenderer
}
-
type cmder interface {name() string
flags() cmdflag
@@ -294,7 +293,6 @@
result(data *cmddata) string
}
-
// return an error message if cmddata matches cmders flags
func (cmd *cmddata) checkReqs(flags cmdflag) (err error) { if flags&free != 0 {@@ -568,7 +566,7 @@
hc.page.Next()
num, _ := strconv.Atoi(data.content)
return hc.page.Pages(num)
-
+
}
return fmt.Sprintf("No page loaded")}
@@ -737,7 +735,7 @@
cmd.doer = func(data *cmddata) string { hc.page = &Page{} localAPI := func(ctx context.Context, pg *mastodon.Pagination) ([]*mastodon.Status, error) {- return hc.client.GetTimelinePublic(ctx, true, pg)
+ return hc.client.GetTimelinePublic(ctx, true, pg)
}
getter := &BasicStatusGetter{getter: localAPI} hc.page.loader = &StatusPages{hc: hc, getter: getter}@@ -756,7 +754,7 @@
cmd.doer = func(data *cmddata) string { hc.page = &Page{} localAPI := func(ctx context.Context, pg *mastodon.Pagination) ([]*mastodon.Status, error) {- return hc.client.GetTimelinePublic(ctx, false, pg)
+ return hc.client.GetTimelinePublic(ctx, false, pg)
}
getter := &BasicStatusGetter{getter: localAPI} hc.page.loader = &StatusPages{hc: hc, getter: getter}@@ -793,8 +791,8 @@
return cmd
}
-//Untested and undocumtend my intance doesn't do this
-//Don't even have the renderer set up here
+// Untested and undocumtend my intance doesn't do this
+// Don't even have the renderer set up here
func (hc *Hellclient) translatecmd() cmder { cmd := &basiccmd{}cmd.hc = hc
@@ -802,10 +800,10 @@
cmd.bflags = status | templater
cmd.doer = func(data *cmddata) string {translated, err := hc.client.TranslateStatus(context.Background(), data.status.ID)
- if err != nil {- return fmt.Sprintf("Translation error: %s\n", err)+ if err != nil {+ return fmt.Sprintf("Translation error: %s\n", err)- }
+ }
hc.PrintObjectProperties(translated)
return ""
}
@@ -824,7 +822,7 @@
return "unlike"
}
-func (like *likecmd) flags() cmdflag {+func (like *likecmd) flags() cmdflag {return status | templater
}
@@ -863,7 +861,7 @@
hc.dispatchAnon(markfunc).Wait()
if err != nil { return fmt.Sprintf("err: %s\n", err)- }
+ }
line, _ := data.templater.render("Bookmarked: $index $username $content $media_descriptions\n")return line
}
@@ -890,12 +888,12 @@
if !postCopy.Bookmarked.(bool) {return "Status not bookmarked.\n"
}
-
+
unmarkfunc = func() { _, err = hc.client.Unbookmark(context.Background(), data.status.ID) }hc.dispatchAnon(unmarkfunc).Wait()
if err != nil { return fmt.Sprintf("err: %s\n", err)- }
+ }
line, _ := data.templater.render("Unbookmarked: $index $username $content $media_descriptions\n")return line
}
@@ -902,7 +900,7 @@
return cmd
}
-func (hc *Hellclient) statusurlcmd(name string, command *string,) cmder {+func (hc *Hellclient) statusurlcmd(name string, command *string) cmder { cmd := &basiccmd{}cmd.hc = hc
cmd.bname = name
@@ -942,7 +940,7 @@
return cmd
}
-//this is using printf fixme
+// this is using printf fixme
func (hc *Hellclient) downloadcmd() cmder { cmd := &basiccmd{}cmd.hc = hc
@@ -979,7 +977,7 @@
_, err := hc.client.AccountFollowDetailed(context.Background(), account.ID, true, relationship.Notifying)
if err != nil {return "Error updating settings\n"
- }
+ }
return fmt.Sprintf("No longer showing RTs from <%s>\n", account.Acct)}
_, err = hc.client.AccountFollowDetailed(context.Background(), account.ID, false, relationship.Notifying)
@@ -1013,7 +1011,7 @@
return cmd
}
-//another printer fixme
+// another printer fixme
func (hc *Hellclient) parentcmd() cmder { cmd := &basiccmd{}cmd.hc = hc
@@ -1035,7 +1033,7 @@
return cmd
}
-//another printer fixme
+// another printer fixme
func (hc *Hellclient) childrencmd() cmder { cmd := &basiccmd{}cmd.hc = hc
@@ -1055,9 +1053,9 @@
hc.printAndIncrement(hc.ctxref, context.Descendants[post])
}
return
- }
- hc.dispatchAnon(childfunc).Wait()
- return ""
+ }
+ hc.dispatchAnon(childfunc).Wait()
+ return ""
}
return cmd
}
@@ -1081,29 +1079,29 @@
return ""
}
var MediaIDs []mastodon.ID
- for _, media := range data.status.MediaAttachments {- MediaIDs = append(MediaIDs, media.ID)
- }
- toot := &mastodon.Toot{- Status: data.content,
- MediaIDs: MediaIDs,
- Sensitive: data.status.Sensitive,
- SpoilerText: data.status.SpoilerText,
- Visibility: data.status.Visibility,
- Language: data.status.Language,
- }
- if data.status.InReplyToID != nil {- id := mastodon.ID(data.status.InReplyToID.(string))
- toot.InReplyToID = id
- }
- editfunc := func() {- _, err = hc.client.UpdateStatus(context.Background(), toot, data.status.ID)
- }
- hc.dispatchAnon(editfunc).Wait()
- if err != nil {- return fmt.Sprintf("err: %s\n", err)- }
- return ""
+ for _, media := range data.status.MediaAttachments {+ MediaIDs = append(MediaIDs, media.ID)
+ }
+ toot := &mastodon.Toot{+ Status: data.content,
+ MediaIDs: MediaIDs,
+ Sensitive: data.status.Sensitive,
+ SpoilerText: data.status.SpoilerText,
+ Visibility: data.status.Visibility,
+ Language: data.status.Language,
+ }
+ if data.status.InReplyToID != nil {+ id := mastodon.ID(data.status.InReplyToID.(string))
+ toot.InReplyToID = id
+ }
+ editfunc := func() {+ _, err = hc.client.UpdateStatus(context.Background(), toot, data.status.ID)
+ }
+ hc.dispatchAnon(editfunc).Wait()
+ if err != nil {+ return fmt.Sprintf("err: %s\n", err)+ }
+ return ""
}
return cmd
}
@@ -1156,52 +1154,52 @@
}
func (hc *Hellclient) followcmd() cmder {- cmd := &basiccmd{}- cmd.hc = hc
- cmd.bname = "follow"
- cmd.bflags = account | acc_resolve
- cmd.doer = func(data *cmddata) string {- account := data.account
- var err error
- var relationship *mastodon.Relationship
- followfunc := func(job *GenericJob) { relationship, err = hc.client.AccountFollow(context.Background(), account.ID) }- followjob := hc.dispatchFunc(followfunc)
- followjob.Wait()
- if err != nil {- return fmt.Sprintf("Error requesting follow: %s\n", err)- }
- if relationship.Following {- return fmt.Sprintf("Successfully followed %s\n", account.Acct)- }
- if relationship.Requested {- return fmt.Sprintf("Follow request sent to %s\n", account.Acct)- }
- return "No error but no follow or request returned in response.\n"
+ cmd := &basiccmd{}+ cmd.hc = hc
+ cmd.bname = "follow"
+ cmd.bflags = account | acc_resolve
+ cmd.doer = func(data *cmddata) string {+ account := data.account
+ var err error
+ var relationship *mastodon.Relationship
+ followfunc := func(job *GenericJob) { relationship, err = hc.client.AccountFollow(context.Background(), account.ID) }+ followjob := hc.dispatchFunc(followfunc)
+ followjob.Wait()
+ if err != nil {+ return fmt.Sprintf("Error requesting follow: %s\n", err)}
- return cmd
+ if relationship.Following {+ return fmt.Sprintf("Successfully followed %s\n", account.Acct)+ }
+ if relationship.Requested {+ return fmt.Sprintf("Follow request sent to %s\n", account.Acct)+ }
+ return "No error but no follow or request returned in response.\n"
+ }
+ return cmd
}
func (hc *Hellclient) unfollowcmd() cmder {- cmd := &basiccmd{}- cmd.hc = hc
- cmd.bname = "unfollow"
- cmd.bflags = account | acc_resolve
- cmd.doer = func(data *cmddata) string {- var relationship *mastodon.Relationship
- account := data.account
- var err error
- unfollowfunc := func(job *GenericJob) { relationship, err = hc.client.AccountUnfollow(context.Background(), account.ID) }- unfollowjob := hc.dispatchFunc(unfollowfunc)
- unfollowjob.Wait()
- if err != nil {- return fmt.Sprintf("Error unfollowing account: %s\n", err)- }
- if !relationship.Following {- return fmt.Sprintf("Successfully unfollowed %s\n", data.index)- }
- return "No error but account is still followed in response\n"
+ cmd := &basiccmd{}+ cmd.hc = hc
+ cmd.bname = "unfollow"
+ cmd.bflags = account | acc_resolve
+ cmd.doer = func(data *cmddata) string {+ var relationship *mastodon.Relationship
+ account := data.account
+ var err error
+ unfollowfunc := func(job *GenericJob) { relationship, err = hc.client.AccountUnfollow(context.Background(), account.ID) }+ unfollowjob := hc.dispatchFunc(unfollowfunc)
+ unfollowjob.Wait()
+ if err != nil {+ return fmt.Sprintf("Error unfollowing account: %s\n", err)}
- return cmd
+ if !relationship.Following {+ return fmt.Sprintf("Successfully unfollowed %s\n", data.index)+ }
+ return "No error but account is still followed in response\n"
+ }
+ return cmd
}
func (hc *Hellclient) filtercmd(name string, filter bool) cmder {@@ -1240,22 +1238,22 @@
var blockfunc func()
if block { blockfunc = func() {- _, err = hc.client.AccountBlock(context.Background(), data.account.ID)
- if err != nil {- result = fmt.Sprintf("Error blocking account: %s.\n", data.account.Acct)- return
- }
- result = fmt.Sprintf("Account blocked: %s\n", data.account.Acct)+ _, err = hc.client.AccountBlock(context.Background(), data.account.ID)
+ if err != nil {+ result = fmt.Sprintf("Error blocking account: %s.\n", data.account.Acct)return
+ }
+ result = fmt.Sprintf("Account blocked: %s\n", data.account.Acct)+ return
}
} else { blockfunc = func() {- _, err := hc.client.AccountUnblock(context.Background(), data.account.ID)
- if err != nil {- result = fmt.Sprintf("Error unblocking account: %s.\n", data.account.Acct)- }
- result = fmt.Sprintf("Account unblocked: %s\n", data.account.Acct)- return
+ _, err := hc.client.AccountUnblock(context.Background(), data.account.ID)
+ if err != nil {+ result = fmt.Sprintf("Error unblocking account: %s.\n", data.account.Acct)+ }
+ result = fmt.Sprintf("Account unblocked: %s\n", data.account.Acct)+ return
}
}
hc.dispatchAnon(blockfunc).Wait()
@@ -1264,7 +1262,7 @@
return cmd
}
-//self printer fixme
+// self printer fixme
func (hc *Hellclient) examinecmd() cmder { cmd := &basiccmd{}cmd.hc = hc
@@ -1308,7 +1306,7 @@
var err error
votefunc := func() {poll, err = hc.client.PollVote(context.Background(), data.status.Poll.ID, voteints...)
- }
+ }
hc.dispatchAnon(votefunc).Wait()
if err != nil { return fmt.Sprintf("Err: %s\n", err)@@ -1374,7 +1372,6 @@
hc.filtercmd("fpost", true),hc.examinecmd(),
hc.votecmd(),
-
}
return cmdarray
}
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@
go 1.23.8
require (
- codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251028231008-1218d098bd98
+ codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251113230229-c103f9ce2762
github.com/ergochat/readline v0.1.3
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/k3a/html2text v1.2.1
--- a/go.sum
+++ b/go.sum
@@ -18,6 +18,8 @@
codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251028230912-df1090ededf3/go.mod h1:uBGYW1AuCWBfm/LaIH4X4SnuWGWcSP4DNH/v/KUUMj8=
codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251028231008-1218d098bd98 h1:RTfvPmEwZjoVbjcZ68HKW57/TfRslY1zLSg83IrhRj0=
codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251028231008-1218d098bd98/go.mod h1:uBGYW1AuCWBfm/LaIH4X4SnuWGWcSP4DNH/v/KUUMj8=
+codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251113230229-c103f9ce2762 h1:aSkTyLw5KHD3/63bH6l5YcUHKznNYGUJ69hlgK7jwLs=
+codeberg.org/penny64/hellclient-go-mastodon v0.0.0-20251113230229-c103f9ce2762/go.mod h1:uBGYW1AuCWBfm/LaIH4X4SnuWGWcSP4DNH/v/KUUMj8=
github.com/ergochat/readline v0.1.3 h1:/DytGTmwdUJcLAe3k3VJgowh5vNnsdifYT6uVaf4pSo=
github.com/ergochat/readline v0.1.3/go.mod h1:o3ux9QLHLm77bq7hDB21UTm6HlV2++IPDMfIfKDuOgY=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
--- a/renderer.go
+++ b/renderer.go
@@ -71,9 +71,18 @@
sb.WriteString(st.status.Visibility)
sb.WriteString(" ") sb.WriteString(fmt.Sprintf("%v\n", st.status.CreatedAt.Local()))+ newline := ""
if !st.status.EditedAt.IsZero() {- sb.WriteString(fmt.Sprintf("EDITED: %v\n", st.status.EditedAt.Local()))+ sb.WriteString(fmt.Sprintf("EDITED: %v ", st.status.EditedAt.Local()))+ newline = "\n"
}
+ client, clientOK := st.status.Application["name"]
+ if clientOK {+ sb.WriteString(client)
+ newline = "\n"
+ }
+ sb.WriteString(newline)
+
if st.status.FavouritesCount > 0 { items = append(items, fmt.Sprintf("Likes:%v", st.status.FavouritesCount))}
--- a/todo.md
+++ b/todo.md
@@ -3,11 +3,11 @@
- [ ] […] long posts
- [ ] Test mode that doesn’t actually send statuses
- [ ] Hashtag search
- - [ ] Poll creation
+ - [ ] Status search
+ - [ ] Profile search
- [ ] lists
- [ ] Interupt handler
- [ ] Load missed posts when we get mastodon error events
- - [ ] Profile search pagination
- [ ] /mute
- [ ] /unmute
- [ ] /pin
@@ -28,6 +28,9 @@
- [ ] plaintext => self authorize oauth
- [ ] -h and -w to specify size of output
- [ ] /history to view edit history
+ - [ ] /pfp view profile picture
+ - [ ] set profile picture
+ - [x] Poll creation
- [x] Poll support
- [x] Hashtags work in /edit
- [x] Thread context in /cat
--
⑨