✨ Interactive feed provider
This commit is contained in:
		
							
								
								
									
										31
									
								
								pkg/internal/grpc/feed.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								pkg/internal/grpc/feed.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | package grpc | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  |  | ||||||
|  | 	iproto "git.solsynth.dev/hypernet/interactive/pkg/proto" | ||||||
|  | 	"git.solsynth.dev/hypernet/nexus/pkg/nex" | ||||||
|  | 	"git.solsynth.dev/hypernet/reader/pkg/internal/models" | ||||||
|  | 	"git.solsynth.dev/hypernet/reader/pkg/internal/services" | ||||||
|  | 	"github.com/samber/lo" | ||||||
|  | 	"google.golang.org/grpc/codes" | ||||||
|  | 	"google.golang.org/grpc/status" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (v *Server) GetFeed(_ context.Context, in *iproto.GetFeedRequest) (*iproto.GetFeedResponse, error) { | ||||||
|  | 	limit := int(in.GetLimit()) | ||||||
|  | 	articles, err := services.GetTodayNewsRandomly(limit, false) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, status.Error(codes.Internal, err.Error()) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &iproto.GetFeedResponse{ | ||||||
|  | 		Items: lo.Map(articles, func(item models.NewsArticle, _ int) *iproto.FeedItem { | ||||||
|  | 			return &iproto.FeedItem{ | ||||||
|  | 				Type:      "reader.news", | ||||||
|  | 				Content:   nex.EncodeMap(item), | ||||||
|  | 				CreatedAt: uint64(item.CreatedAt.Unix()), | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
| @@ -3,6 +3,7 @@ package grpc | |||||||
| import ( | import ( | ||||||
| 	"net" | 	"net" | ||||||
|  |  | ||||||
|  | 	iproto "git.solsynth.dev/hypernet/interactive/pkg/proto" | ||||||
| 	"git.solsynth.dev/hypernet/nexus/pkg/proto" | 	"git.solsynth.dev/hypernet/nexus/pkg/proto" | ||||||
| 	"github.com/spf13/viper" | 	"github.com/spf13/viper" | ||||||
| 	"google.golang.org/grpc" | 	"google.golang.org/grpc" | ||||||
| @@ -12,6 +13,7 @@ import ( | |||||||
|  |  | ||||||
| type Server struct { | type Server struct { | ||||||
| 	proto.UnimplementedDirectoryServiceServer | 	proto.UnimplementedDirectoryServiceServer | ||||||
|  | 	iproto.UnimplementedFeedServiceServer | ||||||
| 	health.UnimplementedHealthServer | 	health.UnimplementedHealthServer | ||||||
|  |  | ||||||
| 	srv *grpc.Server | 	srv *grpc.Server | ||||||
| @@ -23,6 +25,7 @@ func NewGrpc() *Server { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	proto.RegisterDirectoryServiceServer(server.srv, server) | 	proto.RegisterDirectoryServiceServer(server.srv, server) | ||||||
|  | 	iproto.RegisterFeedServiceServer(server.srv, server) | ||||||
| 	health.RegisterHealthServer(server.srv, server) | 	health.RegisterHealthServer(server.srv, server) | ||||||
|  |  | ||||||
| 	reflection.Register(server.srv) | 	reflection.Register(server.srv) | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ func adminTriggerScanTask(c *fiber.Ctx) error { | |||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		count := 0 | 		count := 0 | ||||||
| 		for _, src := range services.NewsSources { | 		for _, src := range services.GetNewsSources() { | ||||||
| 			if !src.Enabled { | 			if !src.Enabled { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ func listNewsArticles(c *fiber.Ctx) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var sources []string | 	var sources []string | ||||||
| 	for _, srv := range services.NewsSources { | 	for _, srv := range services.GetNewsSources() { | ||||||
| 		if !isAdvanced && srv.Advanced { | 		if !isAdvanced && srv.Advanced { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ func getNewsSources(c *fiber.Ctx) error { | |||||||
| 		isAdvanced = true | 		isAdvanced = true | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return c.JSON(lo.Filter(services.NewsSources, func(item models.NewsSource, index int) bool { | 	return c.JSON(lo.Filter(services.GetNewsSources(), func(item models.NewsSource, index int) bool { | ||||||
| 		if !isAdvanced && item.Advanced { | 		if !isAdvanced && item.Advanced { | ||||||
| 			return false | 			return false | ||||||
| 		} | 		} | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								pkg/internal/services/feed.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								pkg/internal/services/feed.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | package services | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"git.solsynth.dev/hypernet/reader/pkg/internal/database" | ||||||
|  | 	"git.solsynth.dev/hypernet/reader/pkg/internal/models" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func GetTodayNewsRandomly(limit int, isAdvanced bool) ([]models.NewsArticle, error) { | ||||||
|  | 	var sources []string | ||||||
|  | 	for _, srv := range GetNewsSources() { | ||||||
|  | 		if !isAdvanced && srv.Advanced { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		sources = append(sources, srv.ID) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var articles []models.NewsArticle | ||||||
|  | 	if err := database.C.Limit(limit). | ||||||
|  | 		Where("source IN ?", sources). | ||||||
|  | 		Where("DATE(created_at) = CURRENT_DATE"). // Created in today | ||||||
|  | 		Order("RANDOM()"). | ||||||
|  | 		Find(&articles).Error; err != nil { | ||||||
|  | 		return articles, err | ||||||
|  | 	} | ||||||
|  | 	return articles, nil | ||||||
|  | } | ||||||
| @@ -17,13 +17,17 @@ import ( | |||||||
| 	"gorm.io/gorm/clause" | 	"gorm.io/gorm/clause" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var NewsSources []models.NewsSource | var newsSources []models.NewsSource | ||||||
|  | 
 | ||||||
|  | func GetNewsSources() []models.NewsSource { | ||||||
|  | 	return newsSources | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| func LoadNewsSources() error { | func LoadNewsSources() error { | ||||||
| 	if err := viper.UnmarshalKey("sources", &NewsSources); err != nil { | 	if err := viper.UnmarshalKey("sources", &newsSources); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	log.Info().Int("count", len(NewsSources)).Msg("Loaded news sources configuration.") | 	log.Info().Int("count", len(newsSources)).Msg("Loaded news sources configuration.") | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -33,7 +37,7 @@ func ScanNewsSourcesNoEager() { | |||||||
| 
 | 
 | ||||||
| func ScanNewsSources(eager ...bool) { | func ScanNewsSources(eager ...bool) { | ||||||
| 	count := 0 | 	count := 0 | ||||||
| 	for _, src := range NewsSources { | 	for _, src := range newsSources { | ||||||
| 		if !src.Enabled { | 		if !src.Enabled { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
		Reference in New Issue
	
	Block a user