mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-31 10:37:13 -04:00 
			
		
		
		
	Add auto refresh of items (#433)
This commit is contained in:
		
						commit
						2641a36352
					
				| @ -28,6 +28,7 @@ using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Postgresql; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using static System.Text.Json.JsonNamingPolicy; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| @ -82,4 +83,38 @@ public class MiscRepository( | ||||
| 			.Concat(context.Movies.Select(x => x.Path)) | ||||
| 			.ToListAsync(); | ||||
| 	} | ||||
| 
 | ||||
| 	public async Task<ICollection<RefreshableItem>> GetRefreshableItems(DateTime end) | ||||
| 	{ | ||||
| 		IQueryable<RefreshableItem> GetItems<T>() | ||||
| 			where T : class, IResource, IRefreshable | ||||
| 		{ | ||||
| 			return context | ||||
| 				.Set<T>() | ||||
| 				.Select(x => new RefreshableItem | ||||
| 				{ | ||||
| 					Kind = CamelCase.ConvertName(typeof(T).Name), | ||||
| 					Id = x.Id, | ||||
| 					RefreshDate = x.NextMetadataRefresh!.Value | ||||
| 				}); | ||||
| 		} | ||||
| 
 | ||||
| 		return await GetItems<Show>() | ||||
| 			.Concat(GetItems<Movie>()) | ||||
| 			.Concat(GetItems<Season>()) | ||||
| 			.Concat(GetItems<Episode>()) | ||||
| 			.Concat(GetItems<Collection>()) | ||||
| 			.Where(x => x.RefreshDate <= end) | ||||
| 			.OrderBy(x => x.RefreshDate) | ||||
| 			.ToListAsync(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public class RefreshableItem | ||||
| { | ||||
| 	public string Kind { get; set; } | ||||
| 
 | ||||
| 	public Guid Id { get; set; } | ||||
| 
 | ||||
| 	public DateTime RefreshDate { get; set; } | ||||
| } | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Kyoo.Abstractions.Models.Permissions; | ||||
| @ -42,4 +43,16 @@ public class Misc(MiscRepository repo) : BaseApi | ||||
| 	{ | ||||
| 		return repo.GetRegisteredPaths(); | ||||
| 	} | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// List items to refresh. | ||||
| 	/// </summary> | ||||
| 	/// <param name="date">The upper limit for the refresh date.</param> | ||||
| 	/// <returns>The items that should be refreshed before the given date</returns> | ||||
| 	[HttpGet("/refreshables")] | ||||
| 	[ProducesResponseType(StatusCodes.Status200OK)] | ||||
| 	public Task<ICollection<RefreshableItem>> GetAllPaths([FromQuery] DateTime? date) | ||||
| 	{ | ||||
| 		return repo.GetRefreshableItems(date ?? DateTime.UtcNow); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -198,7 +198,7 @@ class Matcher: | ||||
| 			"episode": id_episode, | ||||
| 		} | ||||
| 
 | ||||
| 		current = await self._client.get(kind, kyoo_id) | ||||
| 		current = await self._client.get(f"{kind}/{kyoo_id}") | ||||
| 		if self._provider.name not in current["externalId"]: | ||||
| 			logger.error( | ||||
| 				f"Could not refresh metadata of {kind}/{kyoo_id}. Missing provider id." | ||||
|  | ||||
| @ -128,11 +128,9 @@ class KyooClient: | ||||
| 
 | ||||
| 		await self.delete_issue(path) | ||||
| 
 | ||||
| 	async def get( | ||||
| 		self, kind: Literal["movie", "show", "season", "episode", "collection"], id: str | ||||
| 	): | ||||
| 	async def get(self, path: str): | ||||
| 		async with self.client.get( | ||||
| 			f"{self._url}/{kind}/{id}", | ||||
| 			f"{self._url}/{path}", | ||||
| 			headers={"X-API-Key": self._api_key}, | ||||
| 		) as r: | ||||
| 			if not r.ok: | ||||
|  | ||||
| @ -4,6 +4,7 @@ async def main(): | ||||
| 	import logging | ||||
| 	from .monitor import monitor | ||||
| 	from .scanner import scan | ||||
| 	from .refresher import refresh | ||||
| 	from .publisher import Publisher | ||||
| 	from providers.kyoo_client import KyooClient | ||||
| 
 | ||||
| @ -15,4 +16,5 @@ async def main(): | ||||
| 		await asyncio.gather( | ||||
| 			monitor(path, publisher), | ||||
| 			scan(path, publisher, client), | ||||
| 			refresh(publisher, client), | ||||
| 		) | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import os | ||||
| from guessit.jsonutils import json | ||||
| from aio_pika import Message, connect_robust | ||||
| from typing import Literal | ||||
| 
 | ||||
| 
 | ||||
| class Publisher: | ||||
| @ -31,3 +32,11 @@ class Publisher: | ||||
| 
 | ||||
| 	async def delete(self, path: str): | ||||
| 		await self._publish({"action": "delete", "path": path}) | ||||
| 
 | ||||
| 	async def refresh( | ||||
| 		self, | ||||
| 		kind: Literal["collection", "show", "movie", "season", "episode"], | ||||
| 		id: str, | ||||
| 		**_kwargs, | ||||
| 	): | ||||
| 		await self._publish({"action": "refresh", "kind": kind, "id": id}) | ||||
|  | ||||
							
								
								
									
										16
									
								
								scanner/scanner/refresher.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								scanner/scanner/refresher.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| import asyncio | ||||
| from logging import getLogger | ||||
| 
 | ||||
| from providers.kyoo_client import KyooClient | ||||
| from scanner.publisher import Publisher | ||||
| 
 | ||||
| 
 | ||||
| logger = getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| async def refresh(publisher: Publisher, client: KyooClient): | ||||
| 	while True: | ||||
| 		# Check for updates every 4 hours | ||||
| 		await asyncio.sleep(60 * 60 * 4) | ||||
| 		todo = await client.get("refreshables") | ||||
| 		await asyncio.gather(*(publisher.refresh(**x) for x in todo)) | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user