Compare commits

...

7 Commits

Author SHA1 Message Date
localhost_frssoft fa5eaa4442 Just merge with upstream/master 2023-03-18 14:59:40 +03:00
r 5147897c6c Add support for expiring mutes 2022-12-17 08:26:51 +00:00
r 9816045c21 Pass with_relationships param for accounts 2022-12-17 06:58:47 +00:00
r 6002284c5a Show emojis in Mastadon field names 2022-12-17 06:56:39 +00:00
r 887ed241d6 Use cookies for session storage
Remove the server side session storage and store all the session related data
in the client side cookies. This decreases the exposure of the auth tokens.
It also simplifies the installation process as bloat no longer requires write
access to the filesystem.

This is a breaking change, all the existing sessions will stop working.
2022-10-25 14:14:46 +00:00
r b4ccde54a7 Show emojis in Mastadon fields 2022-10-24 04:10:00 +00:00
r 68698a9e1a Remove unused card field from status
Fixes JSON parsing of posts with incompatible card data.
2022-09-23 17:13:22 +00:00
8 changed files with 66 additions and 57 deletions

View File

@ -131,10 +131,7 @@ func RegisterAccount(ctx context.Context, instance string, reason string, userna
func (c *Client) GetAccount(ctx context.Context, id string) (*Account, error) { func (c *Client) GetAccount(ctx context.Context, id string) (*Account, error) {
var account Account var account Account
params := url.Values{} params := url.Values{}
if account.Pleroma != nil { params.Set("with_relationships", strconv.FormatBool(true))
account.MastodonAccount = false
params.Set("with_relationships", "1")
}
err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s", url.PathEscape(string(id))), params, &account, nil) err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s", url.PathEscape(string(id))), params, &account, nil)
if err != nil { if err != nil {
return nil, err return nil, err
@ -361,11 +358,10 @@ func (c *Client) AccountUnblock(ctx context.Context, id string) (*Relationship,
} }
// AccountMute mute the account. // AccountMute mute the account.
func (c *Client) AccountMute(ctx context.Context, id string, notifications *bool) (*Relationship, error) { func (c *Client) AccountMute(ctx context.Context, id string, notifications bool, duration int) (*Relationship, error) {
params := url.Values{} params := url.Values{}
if notifications != nil { params.Set("notifications", strconv.FormatBool(notifications))
params.Set("notifications", strconv.FormatBool(*notifications)) params.Set("duration", strconv.Itoa(duration))
}
var relationship Relationship var relationship Relationship
err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/mute", url.PathEscape(string(id))), params, &relationship, nil) err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/mute", url.PathEscape(string(id))), params, &relationship, nil)
if err != nil { if err != nil {

View File

@ -72,7 +72,6 @@ type Status struct {
MediaAttachments []Attachment `json:"media_attachments"` MediaAttachments []Attachment `json:"media_attachments"`
Mentions []Mention `json:"mentions"` Mentions []Mention `json:"mentions"`
Tags []Tag `json:"tags"` Tags []Tag `json:"tags"`
Card *Card `json:"card"`
Application Application `json:"application"` Application Application `json:"application"`
Language string `json:"language"` Language string `json:"language"`
Pinned interface{} `json:"pinned"` Pinned interface{} `json:"pinned"`
@ -93,22 +92,6 @@ type Context struct {
Descendants []*Status `json:"descendants"` Descendants []*Status `json:"descendants"`
} }
// Card hold information for mastodon card.
type Card struct {
URL string `json:"url"`
Title string `json:"title"`
Description string `json:"description"`
Image string `json:"image"`
Type string `json:"type"`
AuthorName string `json:"author_name"`
AuthorURL string `json:"author_url"`
ProviderName string `json:"provider_name"`
ProviderURL string `json:"provider_url"`
HTML string `json:"html"`
Width int64 `json:"width"`
Height int64 `json:"height"`
}
// GetFavourites return the favorite list of the current user. // GetFavourites return the favorite list of the current user.
func (c *Client) GetFavourites(ctx context.Context, pg *Pagination) ([]*Status, error) { func (c *Client) GetFavourites(ctx context.Context, pg *Pagination) ([]*Status, error) {
var statuses []*Status var statuses []*Status
@ -139,16 +122,6 @@ func (c *Client) GetStatusContext(ctx context.Context, id string) (*Context, err
return &context, nil return &context, nil
} }
// GetStatusCard return status specified by id.
func (c *Client) GetStatusCard(ctx context.Context, id string) (*Card, error) {
var card Card
err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/card", id), nil, &card, nil)
if err != nil {
return nil, err
}
return &card, nil
}
// GetRebloggedBy returns the account list of the user who reblogged the toot of id. // GetRebloggedBy returns the account list of the user who reblogged the toot of id.
func (c *Client) GetRebloggedBy(ctx context.Context, id string, pg *Pagination) ([]*Account, error) { func (c *Client) GetRebloggedBy(ctx context.Context, id string, pg *Pagination) ([]*Account, error) {
var accounts []*Account var accounts []*Account

View File

@ -176,3 +176,8 @@ type FiltersData struct {
*CommonData *CommonData
Filters []*mastodon.Filter Filters []*mastodon.Filter
} }
type MuteData struct {
*CommonData
User *mastodon.Account
}

View File

@ -36,6 +36,7 @@ const (
SettingsPage = "settings.tmpl" SettingsPage = "settings.tmpl"
UserEditPage = "useredit.tmpl" UserEditPage = "useredit.tmpl"
FiltersPage = "filters.tmpl" FiltersPage = "filters.tmpl"
MutePage = "mute.tmpl"
) )
type TemplateData struct { type TemplateData struct {

View File

@ -734,6 +734,19 @@ func (s *service) UserSearchPage(c *client,
return s.renderer.Render(c.rctx, c.w, renderer.UserSearchPage, data) return s.renderer.Render(c.rctx, c.w, renderer.UserSearchPage, data)
} }
func (s *service) MutePage(c *client, id string) (err error) {
user, err := c.GetAccount(c.ctx, id)
if err != nil {
return
}
cdata := s.cdata(c, "Mute"+user.DisplayName+" @"+user.Acct, 0, 0, "")
data := &renderer.UserData{
User: user,
CommonData: cdata,
}
return s.renderer.Render(c.rctx, c.w, renderer.MutePage, data)
}
func (s *service) AboutPage(c *client) (err error) { func (s *service) AboutPage(c *client) (err error) {
cdata := s.cdata(c, "about", 0, 0, "") cdata := s.cdata(c, "about", 0, 0, "")
data := &renderer.AboutData{ data := &renderer.AboutData{
@ -1104,8 +1117,8 @@ func (s *service) Reject(c *client, id string) (err error) {
return c.FollowRequestReject(c.ctx, id) return c.FollowRequestReject(c.ctx, id)
} }
func (s *service) Mute(c *client, id string, notifications *bool) (err error) { func (s *service) Mute(c *client, id string, notifications bool, duration int) (err error) {
_, err = c.AccountMute(c.ctx, id, notifications) _, err = c.AccountMute(c.ctx, id, notifications, duration)
return return
} }

View File

@ -178,6 +178,11 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler {
return s.UserSearchPage(c, id, sq, offset) return s.UserSearchPage(c, id, sq, offset)
}, SESSION, HTML) }, SESSION, HTML)
mutePage := handle(func(c *client) error {
id, _ := mux.Vars(c.r)["id"]
return s.MutePage(c, id)
}, SESSION, HTML)
aboutPage := handle(func(c *client) error { aboutPage := handle(func(c *client) error {
return s.AboutPage(c) return s.AboutPage(c)
}, SESSION, HTML) }, SESSION, HTML)
@ -467,17 +472,13 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler {
mute := handle(func(c *client) error { mute := handle(func(c *client) error {
id, _ := mux.Vars(c.r)["id"] id, _ := mux.Vars(c.r)["id"]
q := c.r.URL.Query() notifications, _ := strconv.ParseBool(c.r.FormValue("notifications"))
var notifications *bool duration, _ := strconv.Atoi(c.r.FormValue("duration"))
if r, ok := q["notifications"]; ok && len(r) > 0 { err := s.Mute(c, id, notifications, duration)
notifications = new(bool)
*notifications = r[0] == "true"
}
err := s.Mute(c, id, notifications)
if err != nil { if err != nil {
return err return err
} }
c.redirect(c.r.FormValue("referrer")) c.redirect("/user/" + id)
return nil return nil
}, CSRF, HTML) }, CSRF, HTML)
@ -805,6 +806,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler {
r.HandleFunc("/user/{id}", userPage).Methods(http.MethodGet) r.HandleFunc("/user/{id}", userPage).Methods(http.MethodGet)
r.HandleFunc("/user/{id}/{type}", userPage).Methods(http.MethodGet) r.HandleFunc("/user/{id}/{type}", userPage).Methods(http.MethodGet)
r.HandleFunc("/usersearch/{id}", userSearchPage).Methods(http.MethodGet) r.HandleFunc("/usersearch/{id}", userSearchPage).Methods(http.MethodGet)
r.HandleFunc("/mute/{id}", mutePage).Methods(http.MethodGet)
r.HandleFunc("/about", aboutPage).Methods(http.MethodGet) r.HandleFunc("/about", aboutPage).Methods(http.MethodGet)
r.HandleFunc("/aboutinstance", aboutInstance).Methods(http.MethodGet) r.HandleFunc("/aboutinstance", aboutInstance).Methods(http.MethodGet)
r.HandleFunc("/emojis", emojisPage).Methods(http.MethodGet) r.HandleFunc("/emojis", emojisPage).Methods(http.MethodGet)

29
templates/mute.tmpl Normal file
View File

@ -0,0 +1,29 @@
{{with .Data}}
{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
<div class="page-title"> Mute {{.User.Acct}} </div>
<form action="/mute/{{.User.ID}}" method="POST">
<input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
<input type="hidden" name="referrer" value="{{$.Ctx.Referrer}}">
<div class="settings-form-field">
<input id="notifications" name="notifications" type="checkbox" value="true" checked>
<label for="notifications"> Mute notifications </label>
</div>
<div class="settings-form-field">
<label for="duration"> Auto unmute </label>
<select id="duration" name="duration">
<option value="0" selected>Disabled</option>
<option value="300">After 5m</option>
<option value="1800">After 30m</option>
<option value="3600">After 1h</option>
<option value="21600">After 6h</option>
<option value="86400">After 1d</option>
<option value="259200">After 3d</option>
<option value="604800">After 7d</option>
</select>
</div>
<button type="submit"> Mute </button>
</form>
{{template "footer.tmpl"}}
{{end}}

View File

@ -81,17 +81,7 @@
<input type="submit" value="unmute" class="btn-link"> <input type="submit" value="unmute" class="btn-link">
</form> </form>
{{else}} {{else}}
<form class="d-inline" action="/mute/{{.User.ID}}" method="post"> <a href="/mute/{{.User.ID}}"> mute </a>
<input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
<input type="hidden" name="referrer" value="{{$.Ctx.Referrer}}">
<input type="submit" value="mute" class="btn-link">
</form>
-
<form class="d-inline" action="/mute/{{.User.ID}}?notifications=false" method="post">
<input type="hidden" name="csrf_token" value="{{$.Ctx.CSRFToken}}">
<input type="hidden" name="referrer" value="{{$.Ctx.Referrer}}">
<input type="submit" value="mute (keep notifications)" class="btn-link">
</form>
{{end}} {{end}}
{{if .User.Pleroma.Relationship.Following}} {{if .User.Pleroma.Relationship.Following}}
- -
@ -144,7 +134,7 @@
{{if .User.Fields}} {{if .User.Fields}}
<div class="user-fields"> <div class="user-fields">
{{range .User.Fields}} {{range .User.Fields}}
<div>{{.Name}} - {{EmojiFilter .Value $.Data.User.Emojis | Raw}}</div> <div>{{EmojiFilter .Name $.Data.User.Emojis | Raw}} - {{EmojiFilter .Value $.Data.User.Emojis | Raw}}</div>
{{end}} {{end}}
</div> </div>
{{end}} {{end}}