Some more
This commit is contained in:
+3274
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,775 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.1
|
||||
// - protoc (unknown)
|
||||
// source: musicfs.proto
|
||||
|
||||
package musicfsv1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
MusicFS_Search_FullMethodName = "/musicfs.v1.MusicFS/Search"
|
||||
MusicFS_SearchStream_FullMethodName = "/musicfs.v1.MusicFS/SearchStream"
|
||||
MusicFS_GetStatus_FullMethodName = "/musicfs.v1.MusicFS/GetStatus"
|
||||
MusicFS_Shutdown_FullMethodName = "/musicfs.v1.MusicFS/Shutdown"
|
||||
MusicFS_GetCacheStats_FullMethodName = "/musicfs.v1.MusicFS/GetCacheStats"
|
||||
MusicFS_ClearCache_FullMethodName = "/musicfs.v1.MusicFS/ClearCache"
|
||||
MusicFS_Prefetch_FullMethodName = "/musicfs.v1.MusicFS/Prefetch"
|
||||
MusicFS_ListOrigins_FullMethodName = "/musicfs.v1.MusicFS/ListOrigins"
|
||||
MusicFS_GetOriginHealth_FullMethodName = "/musicfs.v1.MusicFS/GetOriginHealth"
|
||||
MusicFS_RescanOrigin_FullMethodName = "/musicfs.v1.MusicFS/RescanOrigin"
|
||||
MusicFS_SubscribeEvents_FullMethodName = "/musicfs.v1.MusicFS/SubscribeEvents"
|
||||
)
|
||||
|
||||
// MusicFSClient is the client API for MusicFS service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type MusicFSClient interface {
|
||||
Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error)
|
||||
SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error)
|
||||
GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error)
|
||||
Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error)
|
||||
GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error)
|
||||
ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error)
|
||||
Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error)
|
||||
ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error)
|
||||
GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error)
|
||||
RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error)
|
||||
SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error)
|
||||
}
|
||||
|
||||
type musicFSClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewMusicFSClient(cc grpc.ClientConnInterface) MusicFSClient {
|
||||
return &musicFSClient{cc}
|
||||
}
|
||||
|
||||
func (c *musicFSClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SearchResponse)
|
||||
err := c.cc.Invoke(ctx, MusicFS_Search_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[0], MusicFS_SearchStream_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[SearchRequest, SearchResult]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_SearchStreamClient = grpc.ServerStreamingClient[SearchResult]
|
||||
|
||||
func (c *musicFSClient) GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StatusResponse)
|
||||
err := c.cc.Invoke(ctx, MusicFS_GetStatus_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, MusicFS_Shutdown_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(CacheStats)
|
||||
err := c.cc.Invoke(ctx, MusicFS_GetCacheStats_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ClearCacheResponse)
|
||||
err := c.cc.Invoke(ctx, MusicFS_ClearCache_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[1], MusicFS_Prefetch_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[PrefetchRequest, PrefetchProgress]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_PrefetchClient = grpc.ServerStreamingClient[PrefetchProgress]
|
||||
|
||||
func (c *musicFSClient) ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(OriginsResponse)
|
||||
err := c.cc.Invoke(ctx, MusicFS_ListOrigins_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(OriginHealthResponse)
|
||||
err := c.cc.Invoke(ctx, MusicFS_GetOriginHealth_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *musicFSClient) RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[2], MusicFS_RescanOrigin_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[OriginRequest, SyncProgress]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_RescanOriginClient = grpc.ServerStreamingClient[SyncProgress]
|
||||
|
||||
func (c *musicFSClient) SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[3], MusicFS_SubscribeEvents_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[EventFilter, Event]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_SubscribeEventsClient = grpc.ServerStreamingClient[Event]
|
||||
|
||||
// MusicFSServer is the server API for MusicFS service.
|
||||
// All implementations must embed UnimplementedMusicFSServer
|
||||
// for forward compatibility.
|
||||
type MusicFSServer interface {
|
||||
Search(context.Context, *SearchRequest) (*SearchResponse, error)
|
||||
SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error
|
||||
GetStatus(context.Context, *Empty) (*StatusResponse, error)
|
||||
Shutdown(context.Context, *ShutdownRequest) (*Empty, error)
|
||||
GetCacheStats(context.Context, *Empty) (*CacheStats, error)
|
||||
ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error)
|
||||
Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error
|
||||
ListOrigins(context.Context, *Empty) (*OriginsResponse, error)
|
||||
GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error)
|
||||
RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error
|
||||
SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error
|
||||
mustEmbedUnimplementedMusicFSServer()
|
||||
}
|
||||
|
||||
// UnimplementedMusicFSServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMusicFSServer struct{}
|
||||
|
||||
func (UnimplementedMusicFSServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method Search not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error {
|
||||
return status.Error(codes.Unimplemented, "method SearchStream not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) GetStatus(context.Context, *Empty) (*StatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetStatus not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) Shutdown(context.Context, *ShutdownRequest) (*Empty, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method Shutdown not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) GetCacheStats(context.Context, *Empty) (*CacheStats, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCacheStats not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ClearCache not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error {
|
||||
return status.Error(codes.Unimplemented, "method Prefetch not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) ListOrigins(context.Context, *Empty) (*OriginsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListOrigins not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetOriginHealth not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error {
|
||||
return status.Error(codes.Unimplemented, "method RescanOrigin not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error {
|
||||
return status.Error(codes.Unimplemented, "method SubscribeEvents not implemented")
|
||||
}
|
||||
func (UnimplementedMusicFSServer) mustEmbedUnimplementedMusicFSServer() {}
|
||||
func (UnimplementedMusicFSServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMusicFSServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MusicFSServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeMusicFSServer interface {
|
||||
mustEmbedUnimplementedMusicFSServer()
|
||||
}
|
||||
|
||||
func RegisterMusicFSServer(s grpc.ServiceRegistrar, srv MusicFSServer) {
|
||||
// If the following call panics, it indicates UnimplementedMusicFSServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&MusicFS_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _MusicFS_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SearchRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).Search(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_Search_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).Search(ctx, req.(*SearchRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_SearchStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(SearchRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(MusicFSServer).SearchStream(m, &grpc.GenericServerStream[SearchRequest, SearchResult]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_SearchStreamServer = grpc.ServerStreamingServer[SearchResult]
|
||||
|
||||
func _MusicFS_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).GetStatus(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_GetStatus_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).GetStatus(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ShutdownRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).Shutdown(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_Shutdown_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).Shutdown(ctx, req.(*ShutdownRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_GetCacheStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).GetCacheStats(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_GetCacheStats_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).GetCacheStats(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_ClearCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ClearCacheRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).ClearCache(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_ClearCache_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).ClearCache(ctx, req.(*ClearCacheRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_Prefetch_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(PrefetchRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(MusicFSServer).Prefetch(m, &grpc.GenericServerStream[PrefetchRequest, PrefetchProgress]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_PrefetchServer = grpc.ServerStreamingServer[PrefetchProgress]
|
||||
|
||||
func _MusicFS_ListOrigins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).ListOrigins(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_ListOrigins_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).ListOrigins(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_GetOriginHealth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OriginRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MusicFSServer).GetOriginHealth(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MusicFS_GetOriginHealth_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MusicFSServer).GetOriginHealth(ctx, req.(*OriginRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MusicFS_RescanOrigin_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(OriginRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(MusicFSServer).RescanOrigin(m, &grpc.GenericServerStream[OriginRequest, SyncProgress]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_RescanOriginServer = grpc.ServerStreamingServer[SyncProgress]
|
||||
|
||||
func _MusicFS_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(EventFilter)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(MusicFSServer).SubscribeEvents(m, &grpc.GenericServerStream[EventFilter, Event]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MusicFS_SubscribeEventsServer = grpc.ServerStreamingServer[Event]
|
||||
|
||||
// MusicFS_ServiceDesc is the grpc.ServiceDesc for MusicFS service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var MusicFS_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "musicfs.v1.MusicFS",
|
||||
HandlerType: (*MusicFSServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Search",
|
||||
Handler: _MusicFS_Search_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetStatus",
|
||||
Handler: _MusicFS_GetStatus_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Shutdown",
|
||||
Handler: _MusicFS_Shutdown_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetCacheStats",
|
||||
Handler: _MusicFS_GetCacheStats_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ClearCache",
|
||||
Handler: _MusicFS_ClearCache_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListOrigins",
|
||||
Handler: _MusicFS_ListOrigins_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetOriginHealth",
|
||||
Handler: _MusicFS_GetOriginHealth_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "SearchStream",
|
||||
Handler: _MusicFS_SearchStream_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "Prefetch",
|
||||
Handler: _MusicFS_Prefetch_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "RescanOrigin",
|
||||
Handler: _MusicFS_RescanOrigin_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "SubscribeEvents",
|
||||
Handler: _MusicFS_SubscribeEvents_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "musicfs.proto",
|
||||
}
|
||||
|
||||
const (
|
||||
MetadataService_GetMetadata_FullMethodName = "/musicfs.v1.MetadataService/GetMetadata"
|
||||
MetadataService_UpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/UpdateMetadata"
|
||||
MetadataService_ClearOverlay_FullMethodName = "/musicfs.v1.MetadataService/ClearOverlay"
|
||||
MetadataService_BatchUpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/BatchUpdateMetadata"
|
||||
MetadataService_ImportMetadata_FullMethodName = "/musicfs.v1.MetadataService/ImportMetadata"
|
||||
)
|
||||
|
||||
// MetadataServiceClient is the client API for MetadataService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type MetadataServiceClient interface {
|
||||
GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error)
|
||||
UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error)
|
||||
ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error)
|
||||
BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error)
|
||||
ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error)
|
||||
}
|
||||
|
||||
type metadataServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewMetadataServiceClient(cc grpc.ClientConnInterface) MetadataServiceClient {
|
||||
return &metadataServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *metadataServiceClient) GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(MetadataResponse)
|
||||
err := c.cc.Invoke(ctx, MetadataService_GetMetadata_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *metadataServiceClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(UpdateMetadataResponse)
|
||||
err := c.cc.Invoke(ctx, MetadataService_UpdateMetadata_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *metadataServiceClient) ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ClearOverlayResponse)
|
||||
err := c.cc.Invoke(ctx, MetadataService_ClearOverlay_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *metadataServiceClient) BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[0], MetadataService_BatchUpdateMetadata_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[BatchUpdateRequest, BatchUpdateProgress]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MetadataService_BatchUpdateMetadataClient = grpc.ServerStreamingClient[BatchUpdateProgress]
|
||||
|
||||
func (c *metadataServiceClient) ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[1], MetadataService_ImportMetadata_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[ImportMetadataRequest, ImportProgress]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MetadataService_ImportMetadataClient = grpc.ServerStreamingClient[ImportProgress]
|
||||
|
||||
// MetadataServiceServer is the server API for MetadataService service.
|
||||
// All implementations must embed UnimplementedMetadataServiceServer
|
||||
// for forward compatibility.
|
||||
type MetadataServiceServer interface {
|
||||
GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error)
|
||||
UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error)
|
||||
ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error)
|
||||
BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error
|
||||
ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error
|
||||
mustEmbedUnimplementedMetadataServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedMetadataServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedMetadataServiceServer struct{}
|
||||
|
||||
func (UnimplementedMetadataServiceServer) GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetMetadata not implemented")
|
||||
}
|
||||
func (UnimplementedMetadataServiceServer) UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateMetadata not implemented")
|
||||
}
|
||||
func (UnimplementedMetadataServiceServer) ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ClearOverlay not implemented")
|
||||
}
|
||||
func (UnimplementedMetadataServiceServer) BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error {
|
||||
return status.Error(codes.Unimplemented, "method BatchUpdateMetadata not implemented")
|
||||
}
|
||||
func (UnimplementedMetadataServiceServer) ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error {
|
||||
return status.Error(codes.Unimplemented, "method ImportMetadata not implemented")
|
||||
}
|
||||
func (UnimplementedMetadataServiceServer) mustEmbedUnimplementedMetadataServiceServer() {}
|
||||
func (UnimplementedMetadataServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeMetadataServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to MetadataServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeMetadataServiceServer interface {
|
||||
mustEmbedUnimplementedMetadataServiceServer()
|
||||
}
|
||||
|
||||
func RegisterMetadataServiceServer(s grpc.ServiceRegistrar, srv MetadataServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedMetadataServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&MetadataService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _MetadataService_GetMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetMetadataRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MetadataServiceServer).GetMetadata(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MetadataService_GetMetadata_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MetadataServiceServer).GetMetadata(ctx, req.(*GetMetadataRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MetadataService_UpdateMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UpdateMetadataRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MetadataServiceServer).UpdateMetadata(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MetadataService_UpdateMetadata_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MetadataServiceServer).UpdateMetadata(ctx, req.(*UpdateMetadataRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MetadataService_ClearOverlay_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ClearOverlayRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(MetadataServiceServer).ClearOverlay(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: MetadataService_ClearOverlay_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(MetadataServiceServer).ClearOverlay(ctx, req.(*ClearOverlayRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _MetadataService_BatchUpdateMetadata_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(BatchUpdateRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(MetadataServiceServer).BatchUpdateMetadata(m, &grpc.GenericServerStream[BatchUpdateRequest, BatchUpdateProgress]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MetadataService_BatchUpdateMetadataServer = grpc.ServerStreamingServer[BatchUpdateProgress]
|
||||
|
||||
func _MetadataService_ImportMetadata_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(ImportMetadataRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(MetadataServiceServer).ImportMetadata(m, &grpc.GenericServerStream[ImportMetadataRequest, ImportProgress]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type MetadataService_ImportMetadataServer = grpc.ServerStreamingServer[ImportProgress]
|
||||
|
||||
// MetadataService_ServiceDesc is the grpc.ServiceDesc for MetadataService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var MetadataService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "musicfs.v1.MetadataService",
|
||||
HandlerType: (*MetadataServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetMetadata",
|
||||
Handler: _MetadataService_GetMetadata_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UpdateMetadata",
|
||||
Handler: _MetadataService_UpdateMetadata_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ClearOverlay",
|
||||
Handler: _MetadataService_ClearOverlay_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "BatchUpdateMetadata",
|
||||
Handler: _MetadataService_BatchUpdateMetadata_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "ImportMetadata",
|
||||
Handler: _MetadataService_ImportMetadata_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "musicfs.proto",
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const MatchThreshold = 0.7
|
||||
|
||||
var (
|
||||
punctuationRe = regexp.MustCompile(`[^\w\s]`)
|
||||
yearRe = regexp.MustCompile(`\b(19|20)\d{2}\b`)
|
||||
whitespaceRe = regexp.MustCompile(`\s+`)
|
||||
noiseWords = map[string]struct{}{
|
||||
"remastered": {}, "remaster": {}, "deluxe": {}, "edition": {},
|
||||
"expanded": {}, "anniversary": {}, "special": {}, "limited": {},
|
||||
"collectors": {}, "collector": {}, "bonus": {}, "tracks": {},
|
||||
"standard": {}, "super": {},
|
||||
"flac": {}, "mp3": {}, "aac": {}, "ogg": {}, "wav": {},
|
||||
"24bit": {}, "16bit": {}, "48khz": {}, "44khz": {}, "96khz": {}, "192khz": {},
|
||||
"cd": {}, "vinyl": {}, "lp": {}, "web": {}, "sacd": {},
|
||||
"box": {}, "set": {}, "japan": {}, "shm": {},
|
||||
"singles": {}, "single": {},
|
||||
"pmedia": {},
|
||||
}
|
||||
)
|
||||
|
||||
func normalize(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
s = punctuationRe.ReplaceAllString(s, " ")
|
||||
s = yearRe.ReplaceAllString(s, " ")
|
||||
s = whitespaceRe.ReplaceAllString(s, " ")
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
func tokenize(s string) []string {
|
||||
var tokens []string
|
||||
for _, word := range strings.Fields(s) {
|
||||
if _, noise := noiseWords[word]; !noise && len(word) > 1 {
|
||||
tokens = append(tokens, word)
|
||||
}
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func AlbumMatchScore(albumTitle, torrentTitle, artistName string) float64 {
|
||||
normAlbum := normalize(albumTitle)
|
||||
normTorrent := normalize(torrentTitle)
|
||||
|
||||
if artistName != "" {
|
||||
normArtist := normalize(artistName)
|
||||
normTorrent = strings.Replace(normTorrent, normArtist, "", 1)
|
||||
normTorrent = strings.TrimSpace(whitespaceRe.ReplaceAllString(normTorrent, " "))
|
||||
}
|
||||
|
||||
if normAlbum == "" {
|
||||
return 0
|
||||
}
|
||||
|
||||
if strings.Contains(normTorrent, normAlbum) {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
albumTokens := tokenize(normAlbum)
|
||||
if len(albumTokens) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
torrentTokens := make(map[string]struct{}, len(albumTokens))
|
||||
for _, t := range tokenize(normTorrent) {
|
||||
torrentTokens[t] = struct{}{}
|
||||
}
|
||||
|
||||
var matches int
|
||||
for _, token := range albumTokens {
|
||||
if _, found := torrentTokens[token]; found {
|
||||
matches++
|
||||
continue
|
||||
}
|
||||
for tt := range torrentTokens {
|
||||
if levenshteinClose(token, tt) {
|
||||
matches++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return float64(matches) / float64(len(albumTokens))
|
||||
}
|
||||
|
||||
func levenshteinClose(a, b string) bool {
|
||||
if len(a) < 3 || len(b) < 3 {
|
||||
return false
|
||||
}
|
||||
maxDist := 1
|
||||
if len(a) > 6 {
|
||||
maxDist = 2
|
||||
}
|
||||
return levenshtein(a, b) <= maxDist
|
||||
}
|
||||
|
||||
func levenshtein(a, b string) int {
|
||||
la, lb := len(a), len(b)
|
||||
if la == 0 {
|
||||
return lb
|
||||
}
|
||||
if lb == 0 {
|
||||
return la
|
||||
}
|
||||
|
||||
prev := make([]int, lb+1)
|
||||
curr := make([]int, lb+1)
|
||||
|
||||
for j := 0; j <= lb; j++ {
|
||||
prev[j] = j
|
||||
}
|
||||
|
||||
for i := 1; i <= la; i++ {
|
||||
curr[0] = i
|
||||
for j := 1; j <= lb; j++ {
|
||||
cost := 1
|
||||
if a[i-1] == b[j-1] {
|
||||
cost = 0
|
||||
}
|
||||
curr[j] = min(curr[j-1]+1, min(prev[j]+1, prev[j-1]+cost))
|
||||
}
|
||||
prev, curr = curr, prev
|
||||
}
|
||||
|
||||
return prev[lb]
|
||||
}
|
||||
|
||||
func IsAlbumMatch(albumTitle, torrentTitle, artistName string) bool {
|
||||
return AlbumMatchScore(albumTitle, torrentTitle, artistName) >= MatchThreshold
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package matcher
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAlbumMatchScore(t *testing.T) {
|
||||
tests := []struct {
|
||||
album string
|
||||
torrent string
|
||||
artist string
|
||||
wantMin float64
|
||||
wantMax float64
|
||||
match bool
|
||||
}{
|
||||
{
|
||||
album: "Ain't My Bitch",
|
||||
torrent: "Metallica - Ain't My Bitch (2025) [FLAC]",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.9, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "Ain't My Bitch",
|
||||
torrent: "Metallica - Aint My Bitch Remastered 2025 FLAC",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.9, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "72 Seasons",
|
||||
torrent: "Metallica - 72 Seasons (2023) [24Bit-48kHz] FLAC [PMEDIA] ⭐️",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.9, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "Kill 'Em All",
|
||||
torrent: "Metallica - Kill Em All [1983] FLAC",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.9, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "...And Justice for All",
|
||||
torrent: "Metallica - And Justice For All (Remastered) FLAC",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.7, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "Master of Puppets",
|
||||
torrent: "Metallica - Master of Puppets (Remastered Deluxe Box Set) FLAC",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.9, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "Ain't My Bitch",
|
||||
torrent: "Metallica - Load 1996 (Japan SHM-CD)",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.0, wantMax: 0.3, match: false,
|
||||
},
|
||||
{
|
||||
album: "Ain't My Bitch",
|
||||
torrent: "Metallica - The Memory Remains (Singles, 2026 remastered)",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.0, wantMax: 0.3, match: false,
|
||||
},
|
||||
{
|
||||
album: "Ain't My Bitch",
|
||||
torrent: "Metallica - 72 Seasons (2023) [24Bit-48kHz] FLAC",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.0, wantMax: 0.3, match: false,
|
||||
},
|
||||
{
|
||||
album: "Hardwired...to Self-Destruct",
|
||||
torrent: "Metallica - Hardwired To Self-Destruct (Deluxe 2016) [FLAC]",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.7, wantMax: 1.0, match: true,
|
||||
},
|
||||
{
|
||||
album: "S&M",
|
||||
torrent: "Metallica - S&M (1999) [FLAC]",
|
||||
artist: "Metallica",
|
||||
wantMin: 0.9, wantMax: 1.0, match: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.album+" vs "+tt.torrent, func(t *testing.T) {
|
||||
score := AlbumMatchScore(tt.album, tt.torrent, tt.artist)
|
||||
assert.GreaterOrEqual(t, score, tt.wantMin, "score too low: %.2f", score)
|
||||
assert.LessOrEqual(t, score, tt.wantMax, "score too high: %.2f", score)
|
||||
assert.Equal(t, tt.match, IsAlbumMatch(tt.album, tt.torrent, tt.artist),
|
||||
"match mismatch for score %.2f", score)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user