ref: dd1f814b2de4cab4dde76cd9e78c9c6da2f4455d
dir: /main.go/
package main
import (
"context"
"fmt"
"strconv"
"strings"
mastodon "codeberg.org/penny64/hellclient-go-mastodon"
"github.com/k3a/html2text"
)
func main() {
hc, err := NewHellclient()
if err != nil {
fmt.Printf("Error starting account: %v\n", err)
return
}
rl := hc.rl
client := *hc.client
enablePipeHack(rl)
homeMap := hc.homeMap
lastindex := ""
recentpost := &hc.recentpost
var lastaccount *mastodon.Account
go StreamHomeTimeline(&client, homeMap, hc)
for {
func() {
line, err := rl.Readline()
command, arguments, found := processInput(line, []string{})
//empty line
if command == "" && arguments == "" && err == nil {
hc.togglepause()
return
}
if command == "" && arguments == "" && err != nil {
return
}
//if we didn't get a slash command then the user is just posting
if command == "" && arguments != "" {
hc.dispatchStatus(line, "public")
return
}
result, err := hc.cmdload.run(line)
if err != nil {
fmt.Print(err)
}
fmt.Printf(result)
return
if !found {
fmt.Printf("Command not found: \"%s\"\n", command)
return
}
hc.lock()
defer hc.unlock()
index, content, _ := strings.Cut(arguments, " ")
postItem, postOK := homeMap[index]
//Wether we got a post index or not
foundindex := false
//If there's no index selected load the last post we operated on
if postOK {
foundindex = true
lastindex = index
lastaccount = nil
} else {
postItem, postOK = homeMap[lastindex]
}
var reblogger *mastodon.Status
//Okay now see if the post we end up with is a reblog
if postOK {
if postItem.Reblog != nil {
reblogger = postItem
postItem = postItem.Reblog
}
}
cmdctx, _ := hc.cmdload.processLine(line)
hc.PrintObjectProperties(cmdctx.account)
hc.PrintObjectProperties(cmdctx.status)
hc.PrintObjectProperties(cmdctx.reblogger)
fmt.Println(cmdctx.raw_argument)
fmt.Println(cmdctx.command)
fmt.Println(cmdctx.content)
fmt.Println(cmdctx.index)
accByNameOrRef := func() (account *mastodon.Account) {
if lastaccount != nil {
account = lastaccount
return
}
if lastindex != "" {
account = &postItem.Account
return
}
account = hc.resolveAccount(arguments)
lastindex = ""
postItem = nil
lastaccount = account
return
}
formatter := &StatusFormatter{prefs: hc.preferences, status: postItem, postContext: hc.ctxref, localindex: index}
templater := newStatusTemplateRenderer(formatter)
//Commands require status indexes
switch command {
case "url":
_, indexstr, _ := strings.Cut(arguments, " ")
urlindex, _ := strconv.Atoi(indexstr)
if urlindex > len(hc.homeref.urlmap[index]) {
fmt.Printf("Bad url index\n")
return
}
openItemInOS(hc.preferences.Browser, hc.homeref.urlmap[index][urlindex-1])
return
case "play":
_, indexstr, _ := strings.Cut(arguments, " ")
urlindex, err := strconv.Atoi(indexstr)
if err != nil {
urlindex = 1
}
if urlindex > len(hc.homeref.urlmap[index]) {
fmt.Printf("Bad url index\n")
return
}
openItemInOS(hc.preferences.MediaPlayer, hc.homeref.urlmap[index][urlindex-1])
return
case "view":
err := hc.previewPostImages(postItem, hc.preferences.ImageViewer)
if err != nil {
fmt.Printf("Image preview failed: %v\n", err)
}
return
case "import":
err := hc.previewPostImages(postItem, hc.preferences.MediaImport)
if err != nil {
fmt.Printf("Image preview failed: %v\n", err)
}
return
case "download":
savePostImages(postItem, hc.preferences.Save_Location)
return
case "hrt":
// We want to filter RTs from the RTer
if reblogger != nil {
postItem = reblogger
}
account := accByNameOrRef()
if account == nil {
fmt.Printf("Account lookup failed.\n")
return
}
relationships, err := hc.client.GetAccountRelationships(context.Background(), []string{string(account.ID)})
if err != nil {
fmt.Printf("Error loading relationship.\n")
return
}
relationship := relationships[0]
if !relationship.Following {
fmt.Printf("can't filter rts from user you don't follow!\n")
return
}
if relationship.ShowingReblogs {
_, err := hc.client.AccountFollowDetailed(context.Background(), account.ID, true, relationship.Notifying)
if err != nil {
fmt.Printf("Error updating settings\n")
return
}
fmt.Printf("No longer showing RTs from <%s>\n", account.Acct)
return
}
//Turn them back on if they were off!
_, err = hc.client.AccountFollowDetailed(context.Background(), account.ID, false, relationship.Notifying)
if err != nil {
fmt.Printf("Error updating settings\n")
return
}
fmt.Printf("Now showing RTs from <%s>\n", account.Acct)
return
case "rt":
rtfunc := func() {
rtStatus, err := client.Reblog(context.Background(), postItem.ID)
if err != nil {
fmt.Println(err)
return
}
*recentpost = rtStatus
hc.printAndIncrement(hc.ctxref, rtStatus)
return
}
hc.dispatchAnon(rtfunc).Wait()
return
case "parent":
parentfunc := func() {
if postItem.InReplyToID == nil {
fmt.Printf("%v doesn't have a parent\n", index)
return
}
parentStatus, _ := client.GetStatus(context.Background(), mastodon.ID(postItem.InReplyToID.(string)))
hc.printAndIncrement(hc.ctxref, parentStatus)
return
}
hc.dispatchAnon(parentfunc).Wait()
return
case "children":
childfunc := func() {
context, err := client.GetStatusContext(context.Background(), postItem.ID)
if err != nil {
fmt.Println(err)
return
}
if len(context.Descendants) == 0 {
fmt.Printf("\"%s\" has no children\n", index)
}
for post := range context.Descendants {
hc.printAndIncrement(hc.ctxref, context.Descendants[post])
}
return
}
hc.dispatchAnon(childfunc).Wait()
return
case "edit":
if content == "" || content == " " {
if (postItem == nil) || postItem.Account.ID != hc.currentuser.ID {
fmt.Printf("cannot edit other's statuses!\n")
return
}
fixedHTML, err := prepareForEdit(postItem)
if err != nil {
fmt.Printf("Error loading post HTML: %s\n", err)
return
}
rl.SetDefault(fmt.Sprintf("/edit %v %v", index, html2text.HTML2TextWithOptions(fixedHTML, html2text.WithUnixLineBreaks())))
return
}
var MediaIDs []mastodon.ID
for _, media := range postItem.MediaAttachments {
MediaIDs = append(MediaIDs, media.ID)
}
toot := &mastodon.Toot{
Status: content,
MediaIDs: MediaIDs,
Sensitive: postItem.Sensitive,
SpoilerText: postItem.SpoilerText,
Visibility: postItem.Visibility,
Language: postItem.Language,
}
if postItem.InReplyToID != nil {
id := mastodon.ID(postItem.InReplyToID.(string))
toot.InReplyToID = id
}
editfunc := func() {
_, err = client.UpdateStatus(context.Background(), toot, postItem.ID)
if err != nil {
fmt.Println(err)
return
}
}
hc.dispatchAnon(editfunc).Wait()
return
case "thread":
hc.pause(true)
hc.page = &Page{disablereverse: true}
getter := &ThreadStatusGetter{target: postItem, client: hc.client}
hc.page.loader = &StatusPages{hc: hc, getter: getter}
fmt.Print(hc.page.String())
return
case "pinned":
var account *mastodon.Account
if foundindex || index == "" {
account = &postItem.Account
} else {
account = hc.resolveAccount(index)
if account == nil {
return
}
}
hc.pause(true)
hc.page = &Page{}
hc.page.itembuffer = new([]PageItem)
getter := &PinnedStatusGetter{client: hc.client, ID: account.ID}
hc.page.loader = &StatusPages{hc: hc, getter: getter}
fmt.Print(hc.page.String())
return
case "account":
account := accByNameOrRef()
if account == nil {
fmt.Printf("Account lookup failed.\n")
return
}
hc.pause(true)
hc.page = &Page{}
hc.page.itembuffer = new([]PageItem)
getter := &AccountStatusGetter{client: hc.client, ID: account.ID}
hc.page.loader = &StatusPages{hc: hc, getter: getter}
fmt.Print(hc.page.String())
return
case "unfollow":
account := accByNameOrRef()
if account == nil {
fmt.Printf("Account lookup failed.")
return
}
var relationship *mastodon.Relationship
unfollowfunc := func(job *GenericJob) { relationship, err = hc.client.AccountUnfollow(context.Background(), account.ID) }
unfollowjob := hc.dispatchFunc(unfollowfunc)
unfollowjob.Wait()
if err != nil {
fmt.Printf("Error unfollowing account: %s\n", err)
return
}
if !relationship.Following {
fmt.Printf("Successfully unfollowed %s\n", index)
return
}
fmt.Printf("Unknown failure, account is still followed\n")
return
case "follow":
account := accByNameOrRef()
if account == nil {
fmt.Printf("Account lookup failed.\n")
return
}
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 {
fmt.Printf("Error requesting follow: %s\n", err)
return
}
if relationship.Following {
fmt.Printf("Successfully followed %s\n", account.Acct)
return
}
if relationship.Requested {
fmt.Printf("Follow request sent to %s\n", account.Acct)
return
}
case "fpost":
_, err := hc.filterStatus(postItem)
if err != nil {
fmt.Printf("Error filtering post: %v\n", err)
return
}
url := fmt.Sprintf("%v/statuses/%v", client.Config.Server, postItem.ID)
fmt.Printf("Filtered %v\n", url)
return
case "ufpost":
_, err := hc.unfilterStatus(postItem)
if err != nil {
fmt.Printf("Error unfiltering post: %v\n", err)
return
}
line, _ := templater.render("Unfiltered: %s> $standard_or_subject\n")
fmt.Print(line)
return
case "block":
var account *mastodon.Account
if foundindex || index == "" {
account = &postItem.Account
} else {
account = hc.resolveAccount(index)
if account == nil {
fmt.Printf("Account or index not found.\n")
return
}
}
blockfunc := func() {
_, err := client.AccountBlock(context.Background(), account.ID)
if err != nil {
fmt.Printf("Error blocking account: %s.\n")
return
}
fmt.Printf("Account blocked: %s\n", account.Acct)
}
hc.dispatchAnon(blockfunc).Wait()
return
case "unblock":
var account *mastodon.Account
if foundindex || index == "" {
account = &postItem.Account
} else {
account = hc.resolveAccount(index)
if account == nil {
fmt.Printf("Account or index not found.\n")
return
}
}
unblockfunc := func() {
_, err := client.AccountBlock(context.Background(), account.ID)
if err != nil {
fmt.Printf("Error blocking account: %s.\n")
return
}
fmt.Printf("Account unblocked: %s\n", account.Acct)
}
hc.dispatchAnon(unblockfunc).Wait()
return
}
//Posts that need an index and an argument
if content == "" {
fmt.Printf("\"%v\" requires an argument\n", command)
return
}
}()
}
}