✨ 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 ( | ||||
| 	"net" | ||||
|  | ||||
| 	iproto "git.solsynth.dev/hypernet/interactive/pkg/proto" | ||||
| 	"git.solsynth.dev/hypernet/nexus/pkg/proto" | ||||
| 	"github.com/spf13/viper" | ||||
| 	"google.golang.org/grpc" | ||||
| @@ -12,6 +13,7 @@ import ( | ||||
|  | ||||
| type Server struct { | ||||
| 	proto.UnimplementedDirectoryServiceServer | ||||
| 	iproto.UnimplementedFeedServiceServer | ||||
| 	health.UnimplementedHealthServer | ||||
|  | ||||
| 	srv *grpc.Server | ||||
| @@ -23,6 +25,7 @@ func NewGrpc() *Server { | ||||
| 	} | ||||
|  | ||||
| 	proto.RegisterDirectoryServiceServer(server.srv, server) | ||||
| 	iproto.RegisterFeedServiceServer(server.srv, server) | ||||
| 	health.RegisterHealthServer(server.srv, server) | ||||
|  | ||||
| 	reflection.Register(server.srv) | ||||
|   | ||||
| @@ -28,7 +28,7 @@ func adminTriggerScanTask(c *fiber.Ctx) error { | ||||
|  | ||||
| 	go func() { | ||||
| 		count := 0 | ||||
| 		for _, src := range services.NewsSources { | ||||
| 		for _, src := range services.GetNewsSources() { | ||||
| 			if !src.Enabled { | ||||
| 				continue | ||||
| 			} | ||||
|   | ||||
| @@ -56,7 +56,7 @@ func listNewsArticles(c *fiber.Ctx) error { | ||||
| 	} | ||||
|  | ||||
| 	var sources []string | ||||
| 	for _, srv := range services.NewsSources { | ||||
| 	for _, srv := range services.GetNewsSources() { | ||||
| 		if !isAdvanced && srv.Advanced { | ||||
| 			continue | ||||
| 		} | ||||
|   | ||||
| @@ -14,7 +14,7 @@ func getNewsSources(c *fiber.Ctx) error { | ||||
| 		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 { | ||||
| 			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" | ||||
| ) | ||||
| 
 | ||||
| var NewsSources []models.NewsSource | ||||
| var newsSources []models.NewsSource | ||||
| 
 | ||||
| func GetNewsSources() []models.NewsSource { | ||||
| 	return newsSources | ||||
| } | ||||
| 
 | ||||
| func LoadNewsSources() error { | ||||
| 	if err := viper.UnmarshalKey("sources", &NewsSources); err != nil { | ||||
| 	if err := viper.UnmarshalKey("sources", &newsSources); err != nil { | ||||
| 		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 | ||||
| } | ||||
| 
 | ||||
| @@ -33,7 +37,7 @@ func ScanNewsSourcesNoEager() { | ||||
| 
 | ||||
| func ScanNewsSources(eager ...bool) { | ||||
| 	count := 0 | ||||
| 	for _, src := range NewsSources { | ||||
| 	for _, src := range newsSources { | ||||
| 		if !src.Enabled { | ||||
| 			continue | ||||
| 		} | ||||
		Reference in New Issue
	
	Block a user