Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions database_functions/migration_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ def migration_005_podcast_episode_tables(conn, db_type: str):
ProblemNotified BOOLEAN NOT NULL DEFAULT FALSE,
NextRefreshAt TIMESTAMP DEFAULT (CURRENT_TIMESTAMP + INTERVAL '5 minutes'),
RefreshIntervalMinutes INT,
EditedMetadata VARCHAR(255),
FOREIGN KEY (UserID) REFERENCES "Users"(UserID)
)
""")
Expand Down Expand Up @@ -731,6 +732,7 @@ def migration_005_podcast_episode_tables(conn, db_type: str):
ProblemNotified TINYINT(1) NOT NULL DEFAULT 0,
NextRefreshAt DATETIME NULL DEFAULT (CURRENT_TIMESTAMP + INTERVAL 5 MINUTE),
RefreshIntervalMinutes INT,
EditedMetadata VARCHAR(255),
FOREIGN KEY (UserID) REFERENCES Users(UserID)
)
""")
Expand Down Expand Up @@ -7805,6 +7807,35 @@ def latest(values):
return linked


@register_migration("085", "podcast_edited_metadata", "Podcasts.EditedMetadata: details the user edited, which refreshes keep; every feed is read in full once", requires=["005", "080"])
def migration_085_podcast_edited_metadata(conn, db_type: str) -> None:
"""Refreshes now keep a podcast's name, artwork, author, description and website in step with
its feed. Podcasts.EditedMetadata lists (comma-separated, by lowercase column name) the ones
the user edited by hand, which refreshes leave alone.

The stored validators and body hashes are cleared so the next refresh reads every feed in full
once, bringing podcasts whose feed changed before this release up to date too.
"""
cursor = conn.cursor()
pg = db_type == "postgresql"
podcasts = '"Podcasts"' if pg else "Podcasts"
feeds = '"Feeds"' if pg else "Feeds"
try:
if not _column_exists(cursor, db_type, "Podcasts", "EditedMetadata"):
cursor.execute(f"ALTER TABLE {podcasts} ADD COLUMN EditedMetadata VARCHAR(255)")
not_youtube = "COALESCE(IsYouTubeChannel, FALSE) = FALSE"
for table in (podcasts, feeds):
cursor.execute(
f"UPDATE {table} SET FeedETag = NULL, FeedLastModified = NULL, FeedContentHash = NULL WHERE {not_youtube}"
)
conn.commit()
except Exception:
conn.rollback()
raise
finally:
cursor.close()


@register_migration("118", "gpodder_actions_follow_merged_episodes", "Episode actions point at the shared episode their merged copy became; the copies are deleted", requires=["082", "111"])
def migration_118_gpodder_actions_follow_merged_episodes(conn, db_type: str) -> None:
"""GpodderSyncEpisodeActions.EpisodeID of actions on an episode copy merged by 082 now points
Expand Down
26 changes: 26 additions & 0 deletions mobile/lib/services/pinepods/pinepods_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,32 @@ class PinepodsService {
}
}

// Read a podcast's feed again now and take its current details (name,
// artwork, author, description, website). [resetEdits] also drops the
// user's own edits to them. Throws with the server's message on failure.
Future<void> refreshPodcastDetails(int podcastId, {bool resetEdits = false}) async {
if (_server == null || _apiKey == null) {
throw Exception('Not authenticated');
}

final url = Uri.parse('$_server/api/data/refresh_podcast_details');
// Reading a slow feed can take longer than an ordinary request.
final response = await _client
.post(
url,
headers: {'Api-Key': _apiKey!, 'Content-Type': 'application/json'},
body: jsonEncode({'podcast_id': podcastId, 'reset_edits': resetEdits}),
)
.timeout(const Duration(seconds: 90));
if (response.statusCode != 200) {
String message = 'HTTP ${response.statusCode}';
try {
message = (jsonDecode(response.body) as Map<String, dynamic>)['message'] as String? ?? message;
} catch (_) {}
throw Exception(message);
}
}

// Get a podcast's favorite status.
Future<bool> getPodcastFavoriteStatus(int podcastId, int userId) async {
if (_server == null || _apiKey == null) {
Expand Down
Loading
Loading