Skip to content

Commit d7f485c

Browse files
1.0.7 (#147)
* fix so links don't get messed up by notifications * bump version * truncate accounts and fix login bug * update packages * add follow requests * confirm quit * fix top text * fix multiple feed windows
1 parent f43fec0 commit d7f485c

30 files changed

+638
-289
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ You can find Linux binaries under [releases](https://github.com/RasmusLindroth/t
3939
* `:lists` show a list of your lists
4040
* `:muting` lists users that you have muted
4141
* `:profile` go to your profile
42+
* `:requests` see following requests
4243
* `:saved` alias for bookmarks
4344
* `:tag` followed by the hashtag e.g. `:tag linux`
4445
* `:user` followed by a username e.g. `:user rasmus` to narrow a search include

api/feed.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,13 @@ func (ac *AccountClient) GetMuting(pg *mastodon.Pagination) ([]Item, error) {
223223
return ac.getUserSimilar(fn)
224224
}
225225

226+
func (ac *AccountClient) GetFollowRequests(pg *mastodon.Pagination) ([]Item, error) {
227+
fn := func() ([]*mastodon.Account, error) {
228+
return ac.Client.GetFollowRequests(context.Background(), pg)
229+
}
230+
return ac.getUserSimilar(fn)
231+
}
232+
226233
func (ac *AccountClient) getUserSimilar(fn func() ([]*mastodon.Account, error)) ([]Item, error) {
227234
var items []Item
228235
users, err := fn()

api/user.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,11 @@ func (ac *AccountClient) MuteUser(u *mastodon.Account) (*mastodon.Relationship,
7171
func (ac *AccountClient) UnmuteUser(u *mastodon.Account) (*mastodon.Relationship, error) {
7272
return ac.Client.AccountUnmute(context.Background(), u.ID)
7373
}
74+
75+
func (ac *AccountClient) FollowRequestAccept(u *mastodon.Account) error {
76+
return ac.Client.FollowRequestAuthorize(context.Background(), u.ID)
77+
}
78+
79+
func (ac *AccountClient) FollowRequestDeny(u *mastodon.Account) error {
80+
return ac.Client.FollowRequestReject(context.Background(), u.ID)
81+
}

auth/add.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func AddAccount(ad *AccountData) *mastodon.Client {
8282
}
8383
me, err := client.GetAccountCurrentUser(context.Background())
8484
if err != nil {
85-
fmt.Printf("\nCouldnät get user. Error: %v\nExiting...\n", err)
85+
fmt.Printf("\nCouldn't get user. Error: %v\nExiting...\n", err)
8686
os.Exit(1)
8787
}
8888
acc := Account{

auth/file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (ad *AccountData) Save(filepath string) error {
4848
if err != nil {
4949
return err
5050
}
51-
f, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, 0600)
51+
f, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
5252
if err != nil {
5353
return err
5454
}

auth/load.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ func StartAuth(newUser bool) *AccountData {
1616
accs, err = GetAccounts(path)
1717
}
1818
if err != nil || accs == nil || len(accs.Accounts) == 0 || newUser {
19-
AddAccount(nil)
19+
if err == nil && accs != nil {
20+
AddAccount(accs)
21+
} else {
22+
AddAccount(nil)
23+
}
2024
return StartAuth(false)
2125
}
2226
return accs

config.example.ini

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,42 @@
66
# default=true
77
confirmation=true
88

9+
# Timelines adds windows of feeds. You can customize the number of feeds, what
10+
# they should show and the key to activate them.
11+
#
12+
# Available timelines: home, direct, local, federated, bookmarks, saved,
13+
# favorited, notifications, lists, tag
14+
#
15+
# Tag is special as you need to add the tag after, see the example below.
16+
#
17+
# The syntax is:
18+
# timelines=feed,[name],[keys...]
19+
#
20+
# Tha values in brackets are optional. You can see the syntax for keys under the
21+
# [input] section.
22+
#
23+
# Some examples:
24+
#
25+
# home timeline with the name Home
26+
# timelines=home,Home
27+
#
28+
# local timeline with the name Local and it gets focus when you press 2
29+
# timelines=local,Local,'2'
30+
#
31+
# notification timeline with the name [N]otifications and it gets focus when you
32+
# press n or N
33+
# timelines=notifications,[N]otifications,'n','N'
34+
#
35+
# tag timeline for #linux with the name Linux and it gets focus when you press
36+
# timelines=tag linux,Linux,"F2"
37+
#
38+
#
39+
# If you don't set any timelines it will default to this:
40+
# timelines=home
41+
# timelines=notifications,[N]otifications,'n','N'
42+
#
43+
44+
945
# The date format to be used. See https://godoc.org/time#Time.Format
1046
# default=2006-01-02 15:04
1147
date-format=2006-01-02 15:04
@@ -27,20 +63,11 @@ date-today-format=15:04
2763
# default=-1
2864
date-relative=-1
2965

30-
# The timeline that opens up when you start tut.
31-
# Valid values: home, direct, local, federated
32-
# default=home
33-
timeline=home
34-
3566
# The max width of text before it wraps when displaying toots.
3667
# 0 = no restriction.
3768
# default=0
3869
max-width=0
3970

40-
# If you want to display a list of notifications under your timeline feed.
41-
# default=true
42-
notification-feed=true
43-
4471
# Where do you want the list of toots to be placed?
4572
# Valid values: left, right, top, bottom.
4673
# default=left
@@ -52,11 +79,6 @@ list-placement=left
5279
# default=row
5380
list-split=row
5481

55-
# Hide notification text above list in column split. It's displayed as
56-
# [N]otifications.
57-
# default=false
58-
hide-notification-text=false
59-
6082
# You can change the proportions of the list view in relation to the content
6183
# view list-proportion=1 and content-proportoin=3 will result in the content
6284
# taking up 3 times more space.
@@ -421,6 +443,14 @@ main-prev-feed="",'h','H',"Left"
421443
# default="",'l','L',"Right"
422444
main-next-feed="",'l','L',"Right"
423445

446+
# Focus on the previous feed window
447+
# default="","Backtab"
448+
main-prev-window="","Backtab"
449+
450+
# Focus on the next feed window
451+
# default="","Tab"
452+
main-next-window="","Tab"
453+
424454
# Focus on the notification list
425455
# default="[N]otifications",'n','N'
426456
main-notification-focus="[N]otifications",'n','N'
@@ -497,6 +527,10 @@ user-block="[B]lock","Un[B]lock",'b','B'
497527
# default="[F]ollow","Un[F]ollow",'f','F'
498528
user-follow="[F]ollow","Un[F]ollow",'f','F'
499529

530+
# Follow user
531+
# default="Follow [R]equest","Follow [R]equest",'r','R'
532+
user-follow-request-decide="Follow [R]equest","Follow [R]equest",'r','R'
533+
500534
# Mute user
501535
# default="[M]ute","Un[M]ute",'m','M'
502536
user-mute="[M]ute","Un[M]ute",'m','M'

config/config.go

Lines changed: 118 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ const (
7272
LeaderUser
7373
)
7474

75+
type Timeline struct {
76+
FeedType feed.FeedType
77+
Subaction string
78+
Name string
79+
Key Key
80+
}
81+
7582
type General struct {
7683
Confirmation bool
7784
DateTodayFormat string
@@ -94,6 +101,8 @@ type General struct {
94101
LeaderKey rune
95102
LeaderTimeout int64
96103
LeaderActions []LeaderAction
104+
TimelineName bool
105+
Timelines []Timeline
97106
}
98107

99108
type Style struct {
@@ -306,12 +315,13 @@ type Input struct {
306315
GlobalBack Key
307316
GlobalExit Key
308317

309-
MainHome Key
310-
MainEnd Key
311-
MainPrevFeed Key
312-
MainNextFeed Key
313-
MainNotificationFocus Key
314-
MainCompose Key
318+
MainHome Key
319+
MainEnd Key
320+
MainPrevFeed Key
321+
MainNextFeed Key
322+
MainPrevWindow Key
323+
MainNextWindow Key
324+
MainCompose Key
315325

316326
StatusAvatar Key
317327
StatusBoost Key
@@ -328,14 +338,15 @@ type Input struct {
328338
StatusYank Key
329339
StatusToggleSpoiler Key
330340

331-
UserAvatar Key
332-
UserBlock Key
333-
UserFollow Key
334-
UserMute Key
335-
UserLinks Key
336-
UserUser Key
337-
UserViewFocus Key
338-
UserYank Key
341+
UserAvatar Key
342+
UserBlock Key
343+
UserFollow Key
344+
UserFollowRequestDecide Key
345+
UserMute Key
346+
UserLinks Key
347+
UserUser Key
348+
UserViewFocus Key
349+
UserYank Key
339350

340351
ListOpenFeed Key
341352

@@ -599,6 +610,7 @@ func parseGeneral(cfg *ini.File) General {
599610
parts := strings.Split(l, ",")
600611
if len(parts) != 2 {
601612
fmt.Printf("leader-action must consist of two parts seperated by a comma. Your value is: %s\n", strings.Join(parts, ","))
613+
os.Exit(1)
602614
}
603615
for i, p := range parts {
604616
parts[i] = strings.TrimSpace(p)
@@ -658,6 +670,81 @@ func parseGeneral(cfg *ini.File) General {
658670
}
659671
general.LeaderActions = las
660672
}
673+
674+
general.TimelineName = cfg.Section("general").Key("timeline-show-name").MustBool(true)
675+
var tls []Timeline
676+
timelines := cfg.Section("general").Key("timelines").ValueWithShadows()
677+
for _, l := range timelines {
678+
parts := strings.Split(l, ",")
679+
for i, p := range parts {
680+
parts[i] = strings.TrimSpace(p)
681+
}
682+
if len(parts) == 0 {
683+
fmt.Printf("timelines must consist of atleast one part seperated by a comma. Your value is: %s\n", strings.Join(parts, ","))
684+
os.Exit(1)
685+
}
686+
if len(parts) == 1 {
687+
parts = append(parts, "")
688+
}
689+
cmd := parts[0]
690+
var subaction string
691+
if strings.Contains(parts[0], " ") {
692+
p := strings.Split(cmd, " ")
693+
cmd = p[0]
694+
subaction = strings.Join(p[1:], " ")
695+
}
696+
tl := Timeline{}
697+
switch cmd {
698+
case "home":
699+
tl.FeedType = feed.TimelineHome
700+
case "direct":
701+
tl.FeedType = feed.Conversations
702+
case "local":
703+
tl.FeedType = feed.TimelineLocal
704+
case "federated":
705+
tl.FeedType = feed.TimelineFederated
706+
case "bookmarks":
707+
tl.FeedType = feed.Saved
708+
case "saved":
709+
tl.FeedType = feed.Saved
710+
case "favorited":
711+
tl.FeedType = feed.Favorited
712+
case "notifications":
713+
tl.FeedType = feed.Notification
714+
case "lists":
715+
tl.FeedType = feed.Lists
716+
case "tag":
717+
tl.FeedType = feed.Tag
718+
tl.Subaction = subaction
719+
default:
720+
fmt.Printf("timeline %s is invalid\n", parts[0])
721+
os.Exit(1)
722+
}
723+
tl.Name = parts[1]
724+
if len(parts) > 2 {
725+
vals := []string{""}
726+
vals = append(vals, parts[2:]...)
727+
tl.Key = inputStrOrErr(vals, false)
728+
}
729+
tls = append(tls, tl)
730+
}
731+
if len(tls) == 0 {
732+
tls = append(tls,
733+
Timeline{
734+
FeedType: feed.TimelineHome,
735+
Name: "",
736+
},
737+
)
738+
tls = append(tls,
739+
Timeline{
740+
FeedType: feed.Notification,
741+
Name: "[N]otifications",
742+
Key: inputStrOrErr([]string{"", "'n'", "'N'"}, false),
743+
},
744+
)
745+
}
746+
general.Timelines = tls
747+
661748
return general
662749
}
663750

@@ -893,12 +980,13 @@ func parseInput(cfg *ini.File) Input {
893980
GlobalBack: inputStrOrErr([]string{"\"[Esc]\"", "\"Esc\""}, false),
894981
GlobalExit: inputStrOrErr([]string{"\"[Q]uit\"", "'q'", "'Q'"}, false),
895982

896-
MainHome: inputStrOrErr([]string{"\"\"", "'g'", "\"Home\""}, false),
897-
MainEnd: inputStrOrErr([]string{"\"\"", "'G'", "\"End\""}, false),
898-
MainPrevFeed: inputStrOrErr([]string{"\"\"", "'h'", "'H'", "\"Left\""}, false),
899-
MainNextFeed: inputStrOrErr([]string{"\"\"", "'l'", "'L'", "\"Right\""}, false),
900-
MainNotificationFocus: inputStrOrErr([]string{"\"[N]otifications\"", "'n'", "'N'"}, false),
901-
MainCompose: inputStrOrErr([]string{"\"\"", "'c'", "'C'"}, false),
983+
MainHome: inputStrOrErr([]string{"\"\"", "'g'", "\"Home\""}, false),
984+
MainEnd: inputStrOrErr([]string{"\"\"", "'G'", "\"End\""}, false),
985+
MainPrevFeed: inputStrOrErr([]string{"\"\"", "'h'", "'H'", "\"Left\""}, false),
986+
MainNextFeed: inputStrOrErr([]string{"\"\"", "'l'", "'L'", "\"Right\""}, false),
987+
MainPrevWindow: inputStrOrErr([]string{"\"\"", "\"Backtab\""}, false),
988+
MainNextWindow: inputStrOrErr([]string{"\"\"", "\"Tab\""}, false),
989+
MainCompose: inputStrOrErr([]string{"\"\"", "'c'", "'C'"}, false),
902990

903991
StatusAvatar: inputStrOrErr([]string{"\"[A]vatar\"", "'a'", "'A'"}, false),
904992
StatusBoost: inputStrOrErr([]string{"\"[B]oost\"", "\"Un[B]oost\"", "'b'", "'B'"}, true),
@@ -915,14 +1003,15 @@ func parseInput(cfg *ini.File) Input {
9151003
StatusYank: inputStrOrErr([]string{"\"[Y]ank\"", "'y'", "'Y'"}, false),
9161004
StatusToggleSpoiler: inputStrOrErr([]string{"\"Press [Z] to toggle spoiler\"", "'z'", "'Z'"}, false),
9171005

918-
UserAvatar: inputStrOrErr([]string{"\"[A]vatar\"", "'a'", "'A'"}, false),
919-
UserBlock: inputStrOrErr([]string{"\"[B]lock\"", "\"Un[B]lock\"", "'b'", "'B'"}, true),
920-
UserFollow: inputStrOrErr([]string{"\"[F]ollow\"", "\"Un[F]ollow\"", "'f'", "'F'"}, true),
921-
UserMute: inputStrOrErr([]string{"\"[M]ute\"", "\"Un[M]ute\"", "'m'", "'M'"}, true),
922-
UserLinks: inputStrOrErr([]string{"\"[O]pen\"", "'o'", "'O'"}, false),
923-
UserUser: inputStrOrErr([]string{"\"[U]ser\"", "'u'", "'U'"}, false),
924-
UserViewFocus: inputStrOrErr([]string{"\"[V]iew\"", "'v'", "'V'"}, false),
925-
UserYank: inputStrOrErr([]string{"\"[Y]ank\"", "'y'", "'Y'"}, false),
1006+
UserAvatar: inputStrOrErr([]string{"\"[A]vatar\"", "'a'", "'A'"}, false),
1007+
UserBlock: inputStrOrErr([]string{"\"[B]lock\"", "\"Un[B]lock\"", "'b'", "'B'"}, true),
1008+
UserFollow: inputStrOrErr([]string{"\"[F]ollow\"", "\"Un[F]ollow\"", "'f'", "'F'"}, true),
1009+
UserFollowRequestDecide: inputStrOrErr([]string{"\"Follow [R]equest\"", "\"Follow [R]equest\"", "'r'", "'R'"}, true),
1010+
UserMute: inputStrOrErr([]string{"\"[M]ute\"", "\"Un[M]ute\"", "'m'", "'M'"}, true),
1011+
UserLinks: inputStrOrErr([]string{"\"[O]pen\"", "'o'", "'O'"}, false),
1012+
UserUser: inputStrOrErr([]string{"\"[U]ser\"", "'u'", "'U'"}, false),
1013+
UserViewFocus: inputStrOrErr([]string{"\"[V]iew\"", "'v'", "'V'"}, false),
1014+
UserYank: inputStrOrErr([]string{"\"[Y]ank\"", "'y'", "'Y'"}, false),
9261015

9271016
ListOpenFeed: inputStrOrErr([]string{"\"[O]pen\"", "'o'", "'O'"}, false),
9281017

@@ -954,7 +1043,6 @@ func parseInput(cfg *ini.File) Input {
9541043
ic.MainEnd = inputOrErr(cfg, "main-end", false, ic.MainEnd)
9551044
ic.MainPrevFeed = inputOrErr(cfg, "main-prev-feed", false, ic.MainPrevFeed)
9561045
ic.MainNextFeed = inputOrErr(cfg, "main-next-feed", false, ic.MainNextFeed)
957-
ic.MainNotificationFocus = inputOrErr(cfg, "main-notification-focus", false, ic.MainNotificationFocus)
9581046
ic.MainCompose = inputOrErr(cfg, "main-compose", false, ic.MainCompose)
9591047

9601048
ic.StatusAvatar = inputOrErr(cfg, "status-avatar", false, ic.StatusAvatar)
@@ -975,6 +1063,7 @@ func parseInput(cfg *ini.File) Input {
9751063
ic.UserAvatar = inputOrErr(cfg, "user-avatar", false, ic.UserAvatar)
9761064
ic.UserBlock = inputOrErr(cfg, "user-block", true, ic.UserBlock)
9771065
ic.UserFollow = inputOrErr(cfg, "user-follow", true, ic.UserFollow)
1066+
ic.UserFollowRequestDecide = inputOrErr(cfg, "user-follow-request-decide", true, ic.UserFollowRequestDecide)
9781067
ic.UserMute = inputOrErr(cfg, "user-mute", true, ic.UserMute)
9791068
ic.UserLinks = inputOrErr(cfg, "user-links", false, ic.UserLinks)
9801069
ic.UserUser = inputOrErr(cfg, "user-user", false, ic.UserUser)

0 commit comments

Comments
 (0)