mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 14:52:30 -05:00 
			
		
		
		
	some more hacking away at the timeline code phew
This commit is contained in:
		
					parent
					
						
							
								96048d7f07
							
						
					
				
			
			
				commit
				
					
						86fd23ccd9
					
				
			
		
					 8 changed files with 49 additions and 45 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue