some more hacking away at the timeline code phew
This commit is contained in:
parent
96048d7f07
commit
86fd23ccd9
@ -244,10 +244,6 @@ func (ps *postgresService) GetWhere(where []db.Where, i interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (ps *postgresService) GetWhereMany(i interface{}, where ...model.Where) error {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (ps *postgresService) GetAll(i interface{}) error {
|
||||
if err := ps.conn.Model(i).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
@ -1257,6 +1253,8 @@ func (ps *postgresService) GetNotificationsForAccount(accountID string, limit in
|
||||
CONVERSION FUNCTIONS
|
||||
*/
|
||||
|
||||
// TODO: move these to the type converter, it's bananas that they're here and not there
|
||||
|
||||
func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, originAccountID string, statusID string) ([]*gtsmodel.Mention, error) {
|
||||
ogAccount := >smodel.Account{}
|
||||
if err := ps.conn.Model(ogAccount).Where("id = ?", originAccountID).Select(); err != nil {
|
||||
@ -1341,10 +1339,11 @@ func (ps *postgresService) TagStringsToTags(tags []string, originAccountID strin
|
||||
tag := >smodel.Tag{}
|
||||
// we can use selectorinsert here to create the new tag if it doesn't exist already
|
||||
// inserted will be true if this is a new tag we just created
|
||||
if err := ps.conn.Model(tag).Where("name = ?", t).Select(); err != nil {
|
||||
if err := ps.conn.Model(tag).Where("LOWER(?) = LOWER(?)", pg.Ident("name"), t).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
// tag doesn't exist yet so populate it
|
||||
tag.ID = uuid.NewString()
|
||||
tag.URL = fmt.Sprintf("%s://%s/tags/%s", ps.config.Protocol, ps.config.Host, t)
|
||||
tag.Name = t
|
||||
tag.FirstSeenFromAccountID = originAccountID
|
||||
tag.CreatedAt = time.Now()
|
||||
|
@ -21,7 +21,6 @@ func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Appl
|
||||
ID: thisStatusID,
|
||||
URI: thisStatusURI,
|
||||
URL: thisStatusURL,
|
||||
Content: util.HTMLFormat(form.Status),
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
Local: true,
|
||||
|
@ -248,6 +248,12 @@ func (p *processor) processContent(form *apimodel.AdvancedStatusCreateForm, acco
|
||||
}
|
||||
}
|
||||
|
||||
// format tags nicely
|
||||
for _, tag := range status.GTSTags {
|
||||
tagContent := fmt.Sprintf(`<a href="%s" class="mention hashtag" rel="tag">#<span>%s</span></a>`, tag.URL, tag.Name)
|
||||
content = strings.ReplaceAll(content, fmt.Sprintf("#%s", tag.Name), tagContent)
|
||||
}
|
||||
|
||||
// replace newlines with breaks
|
||||
content = strings.ReplaceAll(content, "\n", "<br />")
|
||||
|
||||
|
@ -143,8 +143,10 @@ func (m *manager) HomeTimeline(timelineAccountID string, maxID string, sinceID s
|
||||
|
||||
var err error
|
||||
var statuses []*apimodel.Status
|
||||
if maxID != "" {
|
||||
statuses, err = t.GetXFromIDOnwards(limit, maxID)
|
||||
if maxID != "" && sinceID != "" {
|
||||
statuses, err = t.GetXBetweenID(limit, maxID, sinceID)
|
||||
} else if maxID != "" {
|
||||
statuses, err = t.GetXBehindID(limit, maxID)
|
||||
} else if sinceID != "" {
|
||||
statuses, err = t.GetXBeforeID(limit, sinceID)
|
||||
} else {
|
||||
|
@ -43,12 +43,21 @@ type Timeline interface {
|
||||
|
||||
// GetXFromTop returns x amount of posts from the top of the timeline, from newest to oldest.
|
||||
GetXFromTop(amount int) ([]*apimodel.Status, error)
|
||||
// GetXFromIDOnwards returns x amount of posts from the given id onwards, from newest to oldest.
|
||||
// This will include the status with the given ID.
|
||||
GetXFromIDOnwards(amount int, fromID string) ([]*apimodel.Status, error)
|
||||
// GetXBehindID returns x amount of posts from the given id onwards, from newest to oldest.
|
||||
// This will NOT include the status with the given ID.
|
||||
//
|
||||
// This corresponds to an api call to /timelines/home?max_id=WHATEVER
|
||||
GetXBehindID(amount int, fromID string) ([]*apimodel.Status, error)
|
||||
// GetXBeforeID returns x amount of posts up to the given id, from newest to oldest.
|
||||
// This will NOT include the status with the given ID.
|
||||
//
|
||||
// This corresponds to an api call to /timelines/home?since_id=WHATEVER
|
||||
GetXBeforeID(amount int, sinceID string) ([]*apimodel.Status, error)
|
||||
// GetXBetweenID returns x amount of posts from the given maxID, up to the given id, from newest to oldest.
|
||||
// This will NOT include the status with the given IDs.
|
||||
//
|
||||
// This corresponds to an api call to /timelines/home?since_id=WHATEVER&max_id=WHATEVER_ELSE
|
||||
GetXBetweenID(amount int, maxID string, sinceID string) ([]*apimodel.Status, error)
|
||||
|
||||
/*
|
||||
INDEXING FUNCTIONS
|
||||
@ -126,10 +135,11 @@ func (t *timeline) PrepareXFromPosition(amount int, desiredPosition int) error {
|
||||
|
||||
if !preparing {
|
||||
// we haven't hit the position we need to prepare from yet
|
||||
position = position + 1
|
||||
if position == desiredPosition {
|
||||
preparing = true
|
||||
continue
|
||||
}
|
||||
position = position + 1
|
||||
} else {
|
||||
if err := t.prepare(entry.statusID); err != nil {
|
||||
return fmt.Errorf("PrepareXFromTop: error preparing status with id %s: %s", entry.statusID, err)
|
||||
@ -205,7 +215,7 @@ func (t *timeline) GetXFromTop(amount int) ([]*apimodel.Status, error) {
|
||||
return statuses, nil
|
||||
}
|
||||
|
||||
func (t *timeline) GetXFromIDOnwards(amount int, fromID string) ([]*apimodel.Status, error) {
|
||||
func (t *timeline) GetXBehindID(amount int, behindID string) ([]*apimodel.Status, error) {
|
||||
// make a slice of statuses with the length we need to return
|
||||
statuses := make([]*apimodel.Status, 0, amount)
|
||||
|
||||
@ -221,7 +231,7 @@ func (t *timeline) GetXFromIDOnwards(amount int, fromID string) ([]*apimodel.Sta
|
||||
if !ok {
|
||||
return nil, errors.New("GetXBehindID: could not parse e as a preparedPostsEntry")
|
||||
}
|
||||
if entry.statusID == fromID {
|
||||
if entry.statusID == behindID {
|
||||
break
|
||||
}
|
||||
position = position + 1
|
||||
@ -245,12 +255,11 @@ func (t *timeline) GetXFromIDOnwards(amount int, fromID string) ([]*apimodel.Sta
|
||||
|
||||
if !serving {
|
||||
// start serving if we've hit the id we're looking for
|
||||
if entry.statusID == fromID {
|
||||
if entry.statusID == behindID {
|
||||
serving = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if serving {
|
||||
} else {
|
||||
// serve up to the amount requested
|
||||
statuses = append(statuses, entry.prepared)
|
||||
served = served + 1
|
||||
@ -297,6 +306,16 @@ servloop:
|
||||
return statuses, nil
|
||||
}
|
||||
|
||||
func (t *timeline) GetXBetweenID(amount int, maxID string, sinceID string) ([]*apimodel.Status, error) {
|
||||
// make a slice of statuses with the length we need to return
|
||||
statuses := make([]*apimodel.Status, 0, amount)
|
||||
|
||||
// if there are no prepared posts, just return the empty slice
|
||||
if t.preparedPosts.data == nil {
|
||||
t.preparedPosts.data = &list.List{}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *timeline) IndexOne(statusCreatedAt time.Time, statusID string) error {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
@ -56,7 +56,7 @@ func (c *converter) StatusToBoost(s *gtsmodel.Status, boostingAccount *gtsmodel.
|
||||
Emojis: []string{},
|
||||
|
||||
// the below fields will be taken from the target status
|
||||
Content: util.HTMLFormat(s.Content),
|
||||
Content: s.Content,
|
||||
ContentWarning: s.ContentWarning,
|
||||
ActivityStreamsType: s.ActivityStreamsType,
|
||||
Sensitive: s.Sensitive,
|
||||
|
@ -41,11 +41,11 @@ var (
|
||||
mentionNameRegex = regexp.MustCompile(mentionNameRegexString)
|
||||
|
||||
// mention regex can be played around with here: https://regex101.com/r/qwM9D3/1
|
||||
mentionFinderRegexString = `(?: |^|\W)?(@[a-zA-Z0-9_]+(?:@[a-zA-Z0-9_\-\.]+)?)(?:[^a-zA-Z0-9]|\W)`
|
||||
mentionFinderRegexString = `(?: |^|\W)(@[a-zA-Z0-9_]+(?:@[a-zA-Z0-9_\-\.]+)?)(?:[^a-zA-Z0-9]|\W|$)?`
|
||||
mentionFinderRegex = regexp.MustCompile(mentionFinderRegexString)
|
||||
|
||||
// hashtag regex can be played with here: https://regex101.com/r/Vhy8pg/1
|
||||
hashtagFinderRegexString = fmt.Sprintf(`(?: |^|\W)?#([a-zA-Z0-9]{1,%d})(?:\b|\r)`, maximumHashtagLength)
|
||||
hashtagFinderRegexString = fmt.Sprintf(`(?:\b)?#(\w{1,%d})(?:\b)`, maximumHashtagLength)
|
||||
hashtagFinderRegex = regexp.MustCompile(hashtagFinderRegexString)
|
||||
|
||||
// emoji shortcode regex can be played with here: https://regex101.com/r/zMDRaG/1
|
||||
|
@ -35,7 +35,7 @@ func DeriveMentionsFromStatus(status string) []string {
|
||||
for _, m := range mentionFinderRegex.FindAllStringSubmatch(status, -1) {
|
||||
mentionedAccounts = append(mentionedAccounts, m[1])
|
||||
}
|
||||
return lower(unique(mentionedAccounts))
|
||||
return unique(mentionedAccounts)
|
||||
}
|
||||
|
||||
// DeriveHashtagsFromStatus takes a plaintext (ie., not html-formatted) status,
|
||||
@ -47,7 +47,7 @@ func DeriveHashtagsFromStatus(status string) []string {
|
||||
for _, m := range hashtagFinderRegex.FindAllStringSubmatch(status, -1) {
|
||||
tags = append(tags, m[1])
|
||||
}
|
||||
return lower(unique(tags))
|
||||
return unique(tags)
|
||||
}
|
||||
|
||||
// DeriveEmojisFromStatus takes a plaintext (ie., not html-formatted) status,
|
||||
@ -59,7 +59,7 @@ func DeriveEmojisFromStatus(status string) []string {
|
||||
for _, m := range emojiFinderRegex.FindAllStringSubmatch(status, -1) {
|
||||
emojis = append(emojis, m[1])
|
||||
}
|
||||
return lower(unique(emojis))
|
||||
return unique(emojis)
|
||||
}
|
||||
|
||||
// ExtractMentionParts extracts the username test_user and the domain example.org
|
||||
@ -94,24 +94,3 @@ func unique(s []string) []string {
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// lower lowercases all strings in a given string slice
|
||||
func lower(s []string) []string {
|
||||
new := []string{}
|
||||
for _, i := range s {
|
||||
new = append(new, strings.ToLower(i))
|
||||
}
|
||||
return new
|
||||
}
|
||||
|
||||
// HTMLFormat takes a plaintext formatted status string, and converts it into
|
||||
// a nice HTML-formatted string.
|
||||
//
|
||||
// This includes:
|
||||
// - Replacing line-breaks with <p>
|
||||
// - Replacing URLs with hrefs.
|
||||
// - Replacing mentions with links to that account's URL as stored in the database.
|
||||
func HTMLFormat(status string) string {
|
||||
// TODO: write proper HTML formatting logic for a status
|
||||
return status
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user