pinakes-server: import directly from extracted crates

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Id43ab8edfd56196d376d72ecc136f6086a6a6964
This commit is contained in:
raf 2026-05-20 21:52:27 +03:00
commit 047801a9da
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
9 changed files with 77 additions and 59 deletions

View file

@ -7,6 +7,11 @@ license.workspace = true
[dependencies]
pinakes-core = { workspace = true }
pinakes-plugin-api = { workspace = true }
pinakes-types = { workspace = true }
pinakes-enrichment = { workspace = true }
pinakes-metadata = { workspace = true }
pinakes-plugin = { workspace = true }
pinakes-sync = { workspace = true }
tokio = { workspace = true }
serde = { workspace = true }

View file

@ -13,10 +13,8 @@ pub struct ExternalMetadataResponse {
pub last_updated: DateTime<Utc>,
}
impl From<pinakes_core::enrichment::ExternalMetadata>
for ExternalMetadataResponse
{
fn from(m: pinakes_core::enrichment::ExternalMetadata) -> Self {
impl From<pinakes_enrichment::ExternalMetadata> for ExternalMetadataResponse {
fn from(m: pinakes_enrichment::ExternalMetadata) -> Self {
let metadata = serde_json::from_str(&m.metadata_json).unwrap_or_else(|e| {
tracing::warn!(
"failed to deserialize external metadata JSON for media {}: {}",

View file

@ -25,8 +25,8 @@ pub struct DeviceResponse {
pub created_at: DateTime<Utc>,
}
impl From<pinakes_core::sync::SyncDevice> for DeviceResponse {
fn from(d: pinakes_core::sync::SyncDevice) -> Self {
impl From<pinakes_sync::SyncDevice> for DeviceResponse {
fn from(d: pinakes_sync::SyncDevice) -> Self {
Self {
id: d.id.0.to_string(),
name: d.name,
@ -72,8 +72,8 @@ pub struct SyncChangeResponse {
pub timestamp: DateTime<Utc>,
}
impl From<pinakes_core::sync::SyncLogEntry> for SyncChangeResponse {
fn from(e: pinakes_core::sync::SyncLogEntry) -> Self {
impl From<pinakes_sync::SyncLogEntry> for SyncChangeResponse {
fn from(e: pinakes_sync::SyncLogEntry) -> Self {
Self {
id: e.id.to_string(),
sequence: e.sequence,
@ -124,8 +124,8 @@ pub struct ConflictResponse {
pub detected_at: DateTime<Utc>,
}
impl From<pinakes_core::sync::SyncConflict> for ConflictResponse {
fn from(c: pinakes_core::sync::SyncConflict) -> Self {
impl From<pinakes_sync::SyncConflict> for ConflictResponse {
fn from(c: pinakes_sync::SyncConflict) -> Self {
Self {
id: c.id.to_string(),
path: c.path,
@ -162,8 +162,8 @@ pub struct UploadSessionResponse {
pub expires_at: DateTime<Utc>,
}
impl From<pinakes_core::sync::UploadSession> for UploadSessionResponse {
fn from(s: pinakes_core::sync::UploadSession) -> Self {
impl From<pinakes_sync::UploadSession> for UploadSessionResponse {
fn from(s: pinakes_sync::UploadSession) -> Self {
Self {
id: s.id.to_string(),
target_path: s.target_path,

View file

@ -236,10 +236,27 @@ async fn main() -> Result<()> {
// Initialize plugin manager if plugins are enabled (needed before job queue)
let plugin_manager = if config.plugins.enabled {
match pinakes_core::plugin::PluginManager::new(
let pm_cfg = {
let p = &config.plugins;
pinakes_plugin::PluginManagerConfig {
plugin_dirs: p.plugin_dirs.clone(),
enable_hot_reload: p.enable_hot_reload,
allow_unsigned: p.allow_unsigned,
max_concurrent_ops: p.max_concurrent_ops,
plugin_timeout_secs: p.plugin_timeout_secs,
timeouts: pinakes_types::config::PluginTimeoutConfig {
capability_query_secs: p.timeouts.capability_query_secs,
processing_secs: p.timeouts.processing_secs,
event_handler_secs: p.timeouts.event_handler_secs,
},
max_consecutive_failures: p.max_consecutive_failures,
trusted_keys: p.trusted_keys.clone(),
}
};
match pinakes_plugin::PluginManager::new(
config.plugins.data_dir.clone(),
config.plugins.cache_dir.clone(),
config.plugins.clone().into(),
pm_cfg,
) {
Ok(pm) => {
tracing::info!("Plugin manager initialized");
@ -538,15 +555,13 @@ async fn main() -> Result<()> {
}
},
JobKind::Enrich { media_ids } => {
use pinakes_core::{
enrichment::{
MetadataEnricher,
books::BookEnricher,
lastfm::LastFmEnricher,
musicbrainz::MusicBrainzEnricher,
tmdb::TmdbEnricher,
},
media_type::MediaCategory,
use pinakes_core::media_type::MediaCategory;
use pinakes_enrichment::{
MetadataEnricher,
books::BookEnricher,
lastfm::LastFmEnricher,
musicbrainz::MusicBrainzEnricher,
tmdb::TmdbEnricher,
};
let enrich_cfg = &config.enrichment;
@ -598,7 +613,7 @@ async fn main() -> Result<()> {
let category = item.media_type.category();
for enricher in &enrichers {
let source = enricher.source();
use pinakes_core::enrichment::EnrichmentSourceType;
use pinakes_enrichment::EnrichmentSourceType;
let applicable = match source {
EnrichmentSourceType::MusicBrainz
| EnrichmentSourceType::LastFm => {
@ -758,7 +773,7 @@ async fn main() -> Result<()> {
let chunked_upload_manager = {
let config_read = config_arc.read().await;
if config_read.sync.enabled {
let manager = pinakes_core::sync::ChunkedUploadManager::new(
let manager = pinakes_sync::ChunkedUploadManager::new(
config_read.sync.temp_upload_dir.clone(),
);
match manager.init().await {

View file

@ -1258,10 +1258,10 @@ pub async fn rename_media(
// Record in sync log
let item = state.storage.get_media(media_id).await?;
let change = pinakes_core::sync::SyncLogEntry {
let change = pinakes_sync::SyncLogEntry {
id: uuid::Uuid::now_v7(),
sequence: 0,
change_type: pinakes_core::sync::SyncChangeType::Moved,
change_type: pinakes_sync::SyncChangeType::Moved,
media_id: Some(media_id),
path: item.path.to_string_lossy().to_string(),
content_hash: Some(item.content_hash.clone()),
@ -1319,10 +1319,10 @@ pub async fn move_media_endpoint(
// Record in sync log
let item = state.storage.get_media(media_id).await?;
let change = pinakes_core::sync::SyncLogEntry {
let change = pinakes_sync::SyncLogEntry {
id: uuid::Uuid::now_v7(),
sequence: 0,
change_type: pinakes_core::sync::SyncChangeType::Moved,
change_type: pinakes_sync::SyncChangeType::Moved,
media_id: Some(media_id),
path: item.path.to_string_lossy().to_string(),
content_hash: Some(item.content_hash.clone()),
@ -1404,10 +1404,10 @@ pub async fn batch_move_media(
continue;
};
let new_path = req.destination.join(file_name);
let change = pinakes_core::sync::SyncLogEntry {
let change = pinakes_sync::SyncLogEntry {
id: uuid::Uuid::now_v7(),
sequence: 0,
change_type: pinakes_core::sync::SyncChangeType::Moved,
change_type: pinakes_sync::SyncChangeType::Moved,
media_id: Some(*media_id),
path: new_path.to_string_lossy().to_string(),
content_hash: None,
@ -1464,10 +1464,10 @@ pub async fn soft_delete_media(
state.storage.soft_delete_media(media_id).await?;
// Record in sync log
let change = pinakes_core::sync::SyncLogEntry {
let change = pinakes_sync::SyncLogEntry {
id: uuid::Uuid::now_v7(),
sequence: 0,
change_type: pinakes_core::sync::SyncChangeType::Deleted,
change_type: pinakes_sync::SyncChangeType::Deleted,
media_id: Some(media_id),
path: item.path.to_string_lossy().to_string(),
content_hash: Some(item.content_hash.clone()),
@ -1524,10 +1524,10 @@ pub async fn restore_media(
let item = state.storage.get_media(media_id).await?;
// Record in sync log
let change = pinakes_core::sync::SyncLogEntry {
let change = pinakes_sync::SyncLogEntry {
id: uuid::Uuid::now_v7(),
sequence: 0,
change_type: pinakes_core::sync::SyncChangeType::Created,
change_type: pinakes_sync::SyncChangeType::Created,
media_id: Some(media_id),
path: item.path.to_string_lossy().to_string(),
content_hash: Some(item.content_hash.clone()),
@ -1681,10 +1681,10 @@ pub async fn permanent_delete_media(
state.storage.delete_media(media_id).await?;
// Record in sync log
let change = pinakes_core::sync::SyncLogEntry {
let change = pinakes_sync::SyncLogEntry {
id: uuid::Uuid::now_v7(),
sequence: 0,
change_type: pinakes_core::sync::SyncChangeType::Deleted,
change_type: pinakes_sync::SyncChangeType::Deleted,
media_id: Some(media_id),
path: item.path.to_string_lossy().to_string(),
content_hash: Some(item.content_hash.clone()),

View file

@ -4,7 +4,7 @@ use axum::{
Json,
extract::{Path, State},
};
use pinakes_core::plugin::PluginManager;
use pinakes_plugin::PluginManager;
use rustc_hash::FxHashMap;
use crate::{

View file

@ -11,19 +11,17 @@ use chrono::Utc;
use pinakes_core::{
config::ConflictResolution,
model::ContentHash,
sync::{
DeviceId,
DeviceType,
SyncChangeType,
SyncConflict,
SyncDevice,
SyncLogEntry,
UploadSession,
UploadStatus,
generate_device_token,
hash_device_token,
update_device_cursor,
},
sync::{generate_device_token, hash_device_token, update_device_cursor},
};
use pinakes_sync::{
DeviceId,
DeviceType,
SyncChangeType,
SyncConflict,
SyncDevice,
SyncLogEntry,
UploadSession,
UploadStatus,
};
use tokio::io::{AsyncReadExt, AsyncSeekExt};
use tokio_util::io::ReaderStream;
@ -176,7 +174,7 @@ pub async fn get_device(
.map_err(|e| ApiError::not_found(format!("Device not found: {e}")))?;
// Verify ownership
if device.user_id != user_id {
if device.user_id.0 != user_id.0 {
return Err(ApiError::forbidden("Not authorized to access this device"));
}
@ -213,7 +211,7 @@ pub async fn update_device(
.map_err(|e| ApiError::not_found(format!("Device not found: {e}")))?;
// Verify ownership
if device.user_id != user_id {
if device.user_id.0 != user_id.0 {
return Err(ApiError::forbidden("Not authorized to update this device"));
}
@ -261,7 +259,7 @@ pub async fn delete_device(
.map_err(|e| ApiError::not_found(format!("Device not found: {e}")))?;
// Verify ownership
if device.user_id != user_id {
if device.user_id.0 != user_id.0 {
return Err(ApiError::forbidden("Not authorized to delete this device"));
}
@ -302,7 +300,7 @@ pub async fn regenerate_token(
.map_err(|e| ApiError::not_found(format!("Device not found: {e}")))?;
// Verify ownership
if device.user_id != user_id {
if device.user_id.0 != user_id.0 {
return Err(ApiError::forbidden(
"Not authorized to regenerate token for this device",
));

View file

@ -5,14 +5,15 @@ use pinakes_core::{
config::Config,
jobs::JobQueue,
managed_storage::ManagedStorageService,
plugin::{PluginManager, PluginPipeline},
plugin::PluginPipeline,
scan::ScanProgress,
scheduler::TaskScheduler,
storage::DynStorageBackend,
sync::ChunkedUploadManager,
transcode::TranscodeService,
webhooks::WebhookDispatcher,
};
use pinakes_plugin::PluginManager;
use pinakes_sync::ChunkedUploadManager;
use tokio::sync::{RwLock, Semaphore};
// Note: Sessions are now stored in the database via StorageBackend

View file

@ -17,7 +17,8 @@ use common::{
test_addr,
};
use http_body_util::BodyExt;
use pinakes_core::{config::PluginsConfig, plugin::PluginManager};
use pinakes_core::config::PluginsConfig;
use pinakes_plugin::PluginManager;
use tower::ServiceExt;
async fn setup_app_with_plugins()
@ -50,7 +51,7 @@ async fn setup_app_with_plugins()
max_concurrent_ops: 2,
plugin_timeout_secs: 10,
timeouts:
pinakes_core::config::PluginTimeoutConfig::default(),
pinakes_types::config::PluginTimeoutConfig::default(),
max_consecutive_failures: 5,
trusted_keys: vec![],
};