initial v1
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>MusicBrainz RSS Feeder</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background-color: #fdfdfd;
|
||||
margin: 0;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
header h1 {
|
||||
font-size: 24px;
|
||||
margin: 0;
|
||||
}
|
||||
header h1 a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
nav a {
|
||||
margin-left: 20px;
|
||||
text-decoration: none;
|
||||
color: #555;
|
||||
}
|
||||
h2, h3 {
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 10px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
form {
|
||||
margin-top: 20px;
|
||||
}
|
||||
input[type="text"] {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
padding: 8px 15px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
.form-inline {
|
||||
display: inline;
|
||||
margin-top: 0;
|
||||
}
|
||||
.item-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1><a href="{{ url_for('index') }}">MusicBrainz RSS Feeder</a></h1>
|
||||
<nav>
|
||||
<a href="{{ url_for('index') }}">Feeds</a>
|
||||
<a href="{{ url_for('settings') }}">Settings</a>
|
||||
</nav>
|
||||
</header>
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Edit Feed: {{ feed.name }}</h2>
|
||||
|
||||
<h3>Artists in this feed</h3>
|
||||
<ul>
|
||||
{% for artist in feed.artists %}
|
||||
<li>
|
||||
{{ artist.name }}
|
||||
<div class="item-actions">
|
||||
<form class="form-inline" action="{{ url_for('remove_artist', feed_id=feed.id, artist_id=artist.id) }}" method="post">
|
||||
<button type="submit">Remove</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>No artists in this feed.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h3>Add Artist</h3>
|
||||
<form onsubmit="return false;">
|
||||
<input type="text" id="artist-search" placeholder="Search for an artist...">
|
||||
</form>
|
||||
<div id="search-results"></div>
|
||||
|
||||
<script>
|
||||
const searchInput = document.getElementById('artist-search');
|
||||
const resultsDiv = document.getElementById('search-results');
|
||||
let searchTimeout;
|
||||
|
||||
searchInput.addEventListener('input', () => {
|
||||
clearTimeout(searchTimeout);
|
||||
const query = searchInput.value;
|
||||
if (query.length < 3) {
|
||||
resultsDiv.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
searchTimeout = setTimeout(() => {
|
||||
fetch(`{{ url_for('search_artist') }}?q=${encodeURIComponent(query)}`)
|
||||
.then(response => response.json())
|
||||
.then(artists => {
|
||||
resultsDiv.innerHTML = '<h4>Search Results</h4>';
|
||||
if (artists.length === 0) {
|
||||
resultsDiv.innerHTML += '<p>No artists found.</p>';
|
||||
return;
|
||||
}
|
||||
const list = document.createElement('ul');
|
||||
artists.forEach(artist => {
|
||||
const item = document.createElement('li');
|
||||
item.innerHTML = `
|
||||
<div>
|
||||
${artist.name} (${artist.country || 'N/A'})
|
||||
</div>
|
||||
<div class="item-actions">
|
||||
<form class="form-inline" action="{{ url_for('add_artist', feed_id=feed.id) }}" method="post">
|
||||
<input type="hidden" name="artist_id" value="${artist.id}">
|
||||
<input type="hidden" name="artist_name" value="${artist.name}">
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
</div>
|
||||
`;
|
||||
list.appendChild(item);
|
||||
});
|
||||
resultsDiv.appendChild(list);
|
||||
});
|
||||
}, 300);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ feed.name }}</title>
|
||||
<link>{{ request.url_root }}</link>
|
||||
<description>Latest album releases for artists in the '{{ feed.name }}' feed.</description>
|
||||
<language>en</language>
|
||||
<lastBuildDate>{{ last_build_date }}</lastBuildDate>
|
||||
<atom:link href="{{ request.url }}" rel="self" type="application/rss+xml" />
|
||||
|
||||
{% for release in releases %}
|
||||
<item>
|
||||
<title>{{ release.artist.name }} - {{ release.title }}</title>
|
||||
<link>https://musicbrainz.org/release/{{ release.id }}</link>
|
||||
<guid isPermaLink="false">{{ release.id }}</guid>
|
||||
<description><![CDATA[
|
||||
<p><b>{{ release.artist.name }}</b> <i>{{ release.title }}</i><br>
|
||||
Release Date: {{ release.date }}</p>
|
||||
{% if release.hasCoverArt %}
|
||||
<img src="http://coverartarchive.org/release/{{ release.id }}/front-500" alt="Cover Art {{ release.title }}">
|
||||
{% endif %}
|
||||
]]></description>
|
||||
{% if release.pub_date %}
|
||||
<pubDate>{{ release.pub_date }}</pubDate>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Feeds</h2>
|
||||
<ul>
|
||||
{% for feed in feeds %}
|
||||
<li>
|
||||
<div>
|
||||
<a href="{{ url_for('edit_feed', feed_id=feed.id) }}">{{ feed.name }}</a>
|
||||
({{ feed.artists|length }})
|
||||
</div>
|
||||
<div class="item-actions">
|
||||
<a href="{{ url_for('get_feed_rss', feed_id=feed.id) }}">RSS</a>
|
||||
<form class="form-inline" action="{{ url_for('delete_feed', feed_id=feed.id) }}" method="post">
|
||||
<button type="submit">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>No feeds configured.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h3>Create New Feed</h3>
|
||||
<form action="{{ url_for('create_feed') }}" method="post">
|
||||
<label for="name">Feed Name:</label>
|
||||
<input type="text" id="name" name="name" required>
|
||||
<button type="submit">Create</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<opml version="2.0">
|
||||
<head>
|
||||
<title>MusicBrainz Artist Feeds</title>
|
||||
</head>
|
||||
<body>
|
||||
<outline text="MusicBrainz Artist Feeds" title="MusicBrainz Artist Feeds">
|
||||
{% for feed in feeds %}
|
||||
<outline type="rss" text="{{ (feed.artists | map(attribute='name') | sort | join(', ')) }}" title="{{ feed.name }} ({{ feed.artists | length }} artists)" xmlUrl="{{ url_for('get_feed_rss', feed_id=feed.id, _external=True) }}"/>
|
||||
{% endfor %}
|
||||
</outline>
|
||||
</body>
|
||||
</opml>
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Settings</h2>
|
||||
<form method="post">
|
||||
<div>
|
||||
<label for="days_back">Days to look back for releases:</label>
|
||||
<input type="number" id="days_back" name="days_back" value="{{ settings.days_back }}" required>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<label for="cache_time_hours">Cache time (hours):</label>
|
||||
<input type="number" id="cache_time_hours" name="cache_time_hours" value="{{ settings.cache_time_hours }}" required>
|
||||
</div>
|
||||
<br>
|
||||
<button type="submit">Save Settings</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user