feat: remove files for one season or episode
DELETE /api/series/{id}/seasons/{n}/files and
DELETE /api/episodes/{id}/files unlink what the scope covers, drop the
matching media_files rows and clear wanted, in one action. 204 on
success, 404 for an unknown season or episode, and a scope with nothing
on disk still clears intent.
Season and episode rows stay: TMDB owns that metadata and the next
refresh would recreate them.
The three scopes share one unlink path. A whole series still resolves to
its title folder (§7.4, atomic); a season or episode resolves to the
recorded file and nothing else, so a narrow call cannot reach a sibling.
The intent clear goes through arr_core::tracking::apply_tracked(false),
the same §4.1 rule #171 landed.
An episode whose file just went is set back to 'missing' when it was
'available', matching what a failed import already does. Closes #174.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4a611a6794
commit
64e28e5930
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "DELETE FROM media_files WHERE owner_kind = 'episode' AND owner_id IN (\n SELECT e.id FROM episodes e JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0ff61f3af9e7185dcd1d506027381c591fab8dcf3e2c223e8cbb82db00e2f02b"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT path AS \"path!: String\"\n FROM media_files WHERE owner_kind = 'episode' AND owner_id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "path!: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "32c562fdb70cabb3265e351583b6ac1579490b29da670fe9062117451911576a"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "DELETE FROM media_files WHERE owner_kind = 'episode' AND owner_id IN (\n SELECT e.id FROM episodes e JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3531a16bd038c149465397a70c24c14ed005683c68f06d322409c5c2b39b84d1"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "UPDATE episodes\n SET wanted = ?,\n state = CASE WHEN state = 'available' THEN 'missing' ELSE state END,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "58fe68be59f015fd8214306483c0d45fcc4b2ac595d3b04efb224b3e426cc1cf"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT r.path AS \"path!: String\"\n FROM roots r\n JOIN series s ON s.root_id = r.id\n JOIN seasons se ON se.series_id = s.id\n JOIN episodes e ON e.season_id = se.id\n WHERE e.id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "path!: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "5b059a2f93a3fb46b6c55e0b665aa55931045af290894e396b3b410123bfd539"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "DELETE FROM media_files WHERE owner_kind = 'episode' AND owner_id IN (\n SELECT e.id FROM episodes e WHERE e.season_id = ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6feaa1abb79ce2a0298bef052d3b731e8ccec88228f7a81b2e8ff5cee76f3fa4"
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE e.season_id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "series_id!: i64",
|
||||
"ordinal": 0,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "id!: i64",
|
||||
"ordinal": 1,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "season_id!: i64",
|
||||
"ordinal": 2,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "season_number!: i64",
|
||||
"ordinal": 3,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "number!: i64",
|
||||
"ordinal": 4,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "title!: String",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "air_date",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "wanted!: bool",
|
||||
"ordinal": 7,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "state!: String",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "vanished!: bool",
|
||||
"ordinal": 9,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "search_attempts!: i64",
|
||||
"ordinal": 10,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "last_searched_at",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "7c638b148b697645d250fe43cf7fcc049e3754e5b1837ff54289e8908523d40c"
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT mf.path AS \"path!: String\"\n FROM media_files mf\n JOIN episodes e ON mf.owner_kind = 'episode' AND e.id = mf.owner_id\n JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "path!: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "87b2e62f51149472db07f32fbc2a548afa40d46b938df101bf3d3b42b01791b4"
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE e.id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "series_id!: i64",
|
||||
"ordinal": 0,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "id!: i64",
|
||||
"ordinal": 1,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "season_id!: i64",
|
||||
"ordinal": 2,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "season_number!: i64",
|
||||
"ordinal": 3,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "number!: i64",
|
||||
"ordinal": 4,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "title!: String",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "air_date",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "wanted!: bool",
|
||||
"ordinal": 7,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "state!: String",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "vanished!: bool",
|
||||
"ordinal": 9,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "search_attempts!: i64",
|
||||
"ordinal": 10,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "last_searched_at",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "90813e43938fcf91b96e444354a5a41b345fec599ba1562ae1fdf617ef49ff54"
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "series_id!: i64",
|
||||
"ordinal": 0,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "id!: i64",
|
||||
"ordinal": 1,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "season_id!: i64",
|
||||
"ordinal": 2,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "season_number!: i64",
|
||||
"ordinal": 3,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "number!: i64",
|
||||
"ordinal": 4,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "title!: String",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "air_date",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "wanted!: bool",
|
||||
"ordinal": 7,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "state!: String",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "vanished!: bool",
|
||||
"ordinal": 9,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "search_attempts!: i64",
|
||||
"ordinal": 10,
|
||||
"type_info": "Integer"
|
||||
},
|
||||
{
|
||||
"name": "last_searched_at",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "97033814ba641d94878f16f23224b49cbad1d65ea0f130d091995bfed87cb844"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT r.path AS \"path!: String\"\n FROM roots r\n JOIN series s ON s.root_id = r.id\n JOIN seasons se ON se.series_id = s.id\n WHERE se.id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "path!: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "98af62bdeb2be99ece2ebcb3567773b3af29299658a21681237cfa11cc806a39"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT mf.path AS \"path!: String\"\n FROM media_files mf\n JOIN episodes e ON mf.owner_kind = 'episode' AND e.id = mf.owner_id\n JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "path!: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "9f2ce3364cd2c227d6dbccf9973d29ca685cdaa1fb2b93124e099b0bbd6a26af"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "DELETE FROM media_files WHERE owner_kind = 'episode' AND owner_id = ?",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "dca537a0b312f758af06608c729790566082d7db2928220fc2f1509e0015423e"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "SELECT mf.path AS \"path!: String\"\n FROM media_files mf\n JOIN episodes e ON mf.owner_kind = 'episode' AND e.id = mf.owner_id\n WHERE e.season_id = ?",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "path!: String",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "e5c40363c81cebf7026b49699981218e15b57d565039f3de2d48b320d3cec92b"
|
||||
}
|
||||
Reference in New Issue
Block a user