diff --git a/back/src/Kyoo.Abstractions/Controllers/IScanner.cs b/back/src/Kyoo.Abstractions/Controllers/IScanner.cs
new file mode 100644
index 00000000..62f14f9f
--- /dev/null
+++ b/back/src/Kyoo.Abstractions/Controllers/IScanner.cs
@@ -0,0 +1,27 @@
+// Kyoo - A portable and vast media library solution.
+// Copyright (c) Kyoo.
+//
+// See AUTHORS.md and LICENSE file in the project root for full license information.
+//
+// Kyoo is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// Kyoo is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Kyoo. If not, see .
+
+using System;
+using System.Threading.Tasks;
+
+namespace Kyoo.Abstractions.Controllers;
+
+public interface IScanner
+{
+ Task SendRefreshRequest(string kind, Guid id);
+}
diff --git a/back/src/Kyoo.Core/Views/Resources/EpisodeApi.cs b/back/src/Kyoo.Core/Views/Resources/EpisodeApi.cs
index 93b3063c..9fb268a0 100644
--- a/back/src/Kyoo.Core/Views/Resources/EpisodeApi.cs
+++ b/back/src/Kyoo.Core/Views/Resources/EpisodeApi.cs
@@ -41,6 +41,29 @@ namespace Kyoo.Core.Api;
public class EpisodeApi(ILibraryManager libraryManager)
: TranscoderApi(libraryManager.Episodes)
{
+ ///
+ /// Refresh
+ ///
+ ///
+ /// Ask a metadata refresh.
+ ///
+ /// The ID or slug of the .
+ /// Nothing
+ /// No episode with the given ID or slug could be found.
+ [HttpPost("{identifier:id}/refresh")]
+ [PartialPermission(Kind.Write)]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public async Task Refresh(Identifier identifier, [FromServices] IScanner scanner)
+ {
+ Guid id = await identifier.Match(
+ id => Task.FromResult(id),
+ async slug => (await libraryManager.Episodes.Get(slug)).Id
+ );
+ await scanner.SendRefreshRequest(nameof(Episode), id);
+ return NoContent();
+ }
+
///
/// Get episode's show
///
diff --git a/back/src/Kyoo.RabbitMq/RabbitMqModule.cs b/back/src/Kyoo.RabbitMq/RabbitMqModule.cs
index aba89bb2..45ff8c39 100644
--- a/back/src/Kyoo.RabbitMq/RabbitMqModule.cs
+++ b/back/src/Kyoo.RabbitMq/RabbitMqModule.cs
@@ -16,6 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see .
+using Kyoo.Abstractions.Controllers;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -41,5 +42,6 @@ public static class RabbitMqModule
return factory.CreateConnection();
});
builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
}
}
diff --git a/back/src/Kyoo.RabbitMq/ScannerProducer.cs b/back/src/Kyoo.RabbitMq/ScannerProducer.cs
new file mode 100644
index 00000000..71c8f97a
--- /dev/null
+++ b/back/src/Kyoo.RabbitMq/ScannerProducer.cs
@@ -0,0 +1,71 @@
+// Kyoo - A portable and vast media library solution.
+// Copyright (c) Kyoo.
+//
+// See AUTHORS.md and LICENSE file in the project root for full license information.
+//
+// Kyoo is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// Kyoo is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Kyoo. If not, see .
+
+using System.Text;
+using System.Text.Json;
+using Kyoo.Abstractions.Controllers;
+using Kyoo.Abstractions.Models;
+using Kyoo.Utils;
+using RabbitMQ.Client;
+
+namespace Kyoo.RabbitMq;
+
+public class ScannerProducer : IScanner
+{
+ private readonly IModel _channel;
+
+ public ScannerProducer(IConnection rabbitConnection)
+ {
+ _channel = rabbitConnection.CreateModel();
+ _channel.QueueDeclare("scanner", exclusive: false, autoDelete: false);
+ }
+
+ private IRepository.ResourceEventHandler _Publish(
+ string exchange,
+ string type,
+ string action
+ )
+ where T : IResource, IQuery
+ {
+ return (T resource) =>
+ {
+ Message message =
+ new()
+ {
+ Action = action,
+ Type = type,
+ Value = resource,
+ };
+ _channel.BasicPublish(
+ exchange,
+ routingKey: message.AsRoutingKey(),
+ body: message.AsBytes()
+ );
+ return Task.CompletedTask;
+ };
+ }
+
+ public Task SendRefreshRequest(string kind, Guid id)
+ {
+ var message = new { Action = "refresh", Kind = kind.ToLowerInvariant(), Id = id };
+ var body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(message, Utility.JsonOptions));
+ _channel.BasicPublish("", routingKey: "scanner", body: body);
+ return Task.CompletedTask;
+ }
+}
+