mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-09 16:44:17 -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 Kyoo.Postgresql;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using static System.Text.Json.JsonNamingPolicy;
|
||||||
|
|
||||||
namespace Kyoo.Core.Controllers;
|
namespace Kyoo.Core.Controllers;
|
||||||
|
|
||||||
@ -82,4 +83,38 @@ public class MiscRepository(
|
|||||||
.Concat(context.Movies.Select(x => x.Path))
|
.Concat(context.Movies.Select(x => x.Path))
|
||||||
.ToListAsync();
|
.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
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Abstractions.Models.Permissions;
|
using Kyoo.Abstractions.Models.Permissions;
|
||||||
@ -42,4 +43,16 @@ public class Misc(MiscRepository repo) : BaseApi
|
|||||||
{
|
{
|
||||||
return repo.GetRegisteredPaths();
|
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,
|
"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"]:
|
if self._provider.name not in current["externalId"]:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"Could not refresh metadata of {kind}/{kyoo_id}. Missing provider id."
|
f"Could not refresh metadata of {kind}/{kyoo_id}. Missing provider id."
|
||||||
|
@ -128,11 +128,9 @@ class KyooClient:
|
|||||||
|
|
||||||
await self.delete_issue(path)
|
await self.delete_issue(path)
|
||||||
|
|
||||||
async def get(
|
async def get(self, path: str):
|
||||||
self, kind: Literal["movie", "show", "season", "episode", "collection"], id: str
|
|
||||||
):
|
|
||||||
async with self.client.get(
|
async with self.client.get(
|
||||||
f"{self._url}/{kind}/{id}",
|
f"{self._url}/{path}",
|
||||||
headers={"X-API-Key": self._api_key},
|
headers={"X-API-Key": self._api_key},
|
||||||
) as r:
|
) as r:
|
||||||
if not r.ok:
|
if not r.ok:
|
||||||
|
@ -4,6 +4,7 @@ async def main():
|
|||||||
import logging
|
import logging
|
||||||
from .monitor import monitor
|
from .monitor import monitor
|
||||||
from .scanner import scan
|
from .scanner import scan
|
||||||
|
from .refresher import refresh
|
||||||
from .publisher import Publisher
|
from .publisher import Publisher
|
||||||
from providers.kyoo_client import KyooClient
|
from providers.kyoo_client import KyooClient
|
||||||
|
|
||||||
@ -15,4 +16,5 @@ async def main():
|
|||||||
await asyncio.gather(
|
await asyncio.gather(
|
||||||
monitor(path, publisher),
|
monitor(path, publisher),
|
||||||
scan(path, publisher, client),
|
scan(path, publisher, client),
|
||||||
|
refresh(publisher, client),
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from guessit.jsonutils import json
|
from guessit.jsonutils import json
|
||||||
from aio_pika import Message, connect_robust
|
from aio_pika import Message, connect_robust
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
class Publisher:
|
class Publisher:
|
||||||
@ -31,3 +32,11 @@ class Publisher:
|
|||||||
|
|
||||||
async def delete(self, path: str):
|
async def delete(self, path: str):
|
||||||
await self._publish({"action": "delete", "path": path})
|
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