Compare commits

...

8 Commits

Author SHA1 Message Date
mi
c7cd40f5a9 🔨 generate rss 2025-11-06 22:08:29 +10:00
mi
68bfb237df 🔨 new comic script 2025-11-06 21:59:15 +10:00
mi
8f378b817e 💄 remove border on comic 2025-11-06 21:45:33 +10:00
mi
368a7f57a4 :clownface: example absent author note 2025-11-06 21:43:01 +10:00
mi
b0987ceff3 author note 2025-11-06 21:42:20 +10:00
mi
be8ea1c34f optional title 2025-11-06 21:38:51 +10:00
mi
0d229fd442 🚚 move out comics data 2025-11-06 21:32:40 +10:00
mi
b8a75571a5 🐛 fallback image was causing infinite loop 2025-11-06 21:24:38 +10:00
9 changed files with 196 additions and 42 deletions

3
.gitignore vendored
View File

@@ -1,2 +1,5 @@
.idea
.venv
# This should be generated on deploy
static/feed.rss

29
app.py
View File

@@ -1,38 +1,11 @@
from flask import Flask, render_template, abort
from comics_data import COMICS
app = Flask(__name__)
# Configuration
app.config['SECRET_KEY'] = 'your-secret-key-here' # Change this in production
# Sample comic data (in production, this would come from a database)
COMICS = [
{
'number': 1,
'title': 'First Comic',
'filename': 'comic-001.png',
'date': '2025-01-01',
'alt_text': 'The very first comic',
'transcript': 'This is where your comic journey begins!'
},
{
'number': 2,
'title': 'Second Comic',
'filename': 'comic-002.png',
'date': '2025-01-08',
'alt_text': 'The second comic',
'transcript': 'The adventure continues...'
},
{
'number': 3,
'title': 'Third Comic',
'filename': 'comic-003.png',
'date': '2025-01-15',
'alt_text': 'The third comic',
'transcript': 'Things are getting interesting!'
},
]
def get_comic_by_number(number):
"""Get a comic by its number"""

27
comics_data.py Normal file
View File

@@ -0,0 +1,27 @@
# Comic data
# Edit this file to add, remove, or modify comics
COMICS = [
{
'number': 1,
'title': 'First Comic',
'filename': 'comic-001.png',
'date': '2025-01-01',
'alt_text': 'The very first comic',
'author_note': 'This is where your comic journey begins!'
},
{
'number': 2,
'filename': 'comic-002.png',
'date': '2025-01-08',
'alt_text': 'The second comic',
},
{
'number': 3,
'title': 'Third Comic',
'filename': 'comic-003.png',
'date': '2025-01-15',
'alt_text': 'The third comic',
'author_note': 'Things are getting interesting!'
},
]

56
scripts/add_comic.py Executable file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env python3
"""
Script to add a new comic entry to comics_data.py with reasonable defaults
"""
import sys
import os
from datetime import datetime
# Add parent directory to path so we can import comics_data
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from comics_data import COMICS
def main():
"""Add a new comic entry with defaults"""
# Get next number
number = max(comic['number'] for comic in COMICS) + 1 if COMICS else 1
# Create entry with defaults
comic = {
'number': number,
'filename': f'comic-{number:03d}.png',
'date': datetime.now().strftime('%Y-%m-%d'),
'alt_text': f'Comic #{number}',
}
# Get path to comics_data.py
script_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(script_dir)
comics_file = os.path.join(parent_dir, 'comics_data.py')
# Read file
with open(comics_file, 'r') as f:
content = f.read()
# Format new entry
entry_str = f""" {{
'number': {comic['number']},
'filename': {repr(comic['filename'])},
'date': {repr(comic['date'])},
'alt_text': {repr(comic['alt_text'])}
}}"""
# Insert before closing bracket
insert_pos = content.rfind(']')
new_content = content[:insert_pos] + entry_str + ",\n" + content[insert_pos:]
# Write back
with open(comics_file, 'w') as f:
f.write(new_content)
print(f"Added comic #{number}")
if __name__ == '__main__':
main()

97
scripts/generate_rss.py Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python3
"""
Script to generate an RSS feed for the comic
"""
import sys
import os
from datetime import datetime
from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom import minidom
# Add parent directory to path so we can import comics_data
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from comics_data import COMICS
# Configuration - update these for your site
SITE_URL = "http://localhost:5000" # Change to your actual domain
SITE_TITLE = "Sunday Comics"
SITE_DESCRIPTION = "A webcomic about life, the universe, and everything"
SITE_LANGUAGE = "en-us"
def generate_rss():
"""Generate RSS feed from COMICS data"""
# Create RSS root
rss = Element('rss', version='2.0')
channel = SubElement(rss, 'channel')
# Channel metadata
SubElement(channel, 'title').text = SITE_TITLE
SubElement(channel, 'link').text = SITE_URL
SubElement(channel, 'description').text = SITE_DESCRIPTION
SubElement(channel, 'language').text = SITE_LANGUAGE
SubElement(channel, 'lastBuildDate').text = datetime.now().strftime('%a, %d %b %Y %H:%M:%S +0000')
# Add items for each comic (reversed to show newest first)
for comic in reversed(COMICS):
item = SubElement(channel, 'item')
# Title
title = comic.get('title', f"#{comic['number']}")
SubElement(item, 'title').text = title
# Link to comic page
link = f"{SITE_URL}/comic/{comic['number']}"
SubElement(item, 'link').text = link
SubElement(item, 'guid', isPermaLink='true').text = link
# Description (include author note if present)
description = f"Comic #{comic['number']}"
if comic.get('author_note'):
description += f"\n\n{comic['author_note']}"
SubElement(item, 'description').text = description
# Publication date
try:
pub_date = datetime.strptime(comic['date'], '%Y-%m-%d')
SubElement(item, 'pubDate').text = pub_date.strftime('%a, %d %b %Y 00:00:00 +0000')
except:
pass
# Image enclosure
image_url = f"{SITE_URL}/static/images/{comic['filename']}"
SubElement(item, 'enclosure', url=image_url, type='image/png', length='0')
# Convert to pretty XML
xml_str = minidom.parseString(tostring(rss)).toprettyxml(indent=' ')
# Remove extra blank lines
xml_str = '\n'.join([line for line in xml_str.split('\n') if line.strip()])
return xml_str
def main():
"""Generate and save RSS feed"""
# Get path to static folder
script_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(script_dir)
static_dir = os.path.join(parent_dir, 'static')
# Create static directory if it doesn't exist
os.makedirs(static_dir, exist_ok=True)
# Generate RSS
rss_content = generate_rss()
# Save to file
rss_file = os.path.join(static_dir, 'feed.rss')
with open(rss_file, 'w', encoding='utf-8') as f:
f.write(rss_content)
print(f"RSS feed generated: {rss_file}")
print(f"Total comics: {len(COMICS)}")
if __name__ == '__main__':
main()

View File

@@ -183,7 +183,6 @@ main {
.comic-image {
text-align: center;
margin-bottom: 1.5rem;
border: 2px solid #000;
padding: 0.5rem;
background: #fff;
}

View File

@@ -12,10 +12,9 @@
<div class="archive-item">
<a href="{{ url_for('comic', comic_id=comic.number) }}">
<img src="{{ url_for('static', filename='images/thumbs/' + comic.filename) }}"
alt="{{ comic.title }}"
onerror="this.src='{{ url_for('static', filename='images/' + comic.filename) }}'">
alt="{{ comic.title if comic.title else '#' ~ comic.number }}">
<div class="archive-info">
<h3>#{{ comic.number }}: {{ comic.title }}</h3>
<h3>#{{ comic.number }}{% if comic.title %}: {{ comic.title }}{% endif %}</h3>
<p class="archive-date">{{ comic.date }}</p>
</div>
</a>

View File

@@ -3,13 +3,13 @@
{% block content %}
<div class="comic-container">
<div class="comic-header">
<h1>{{ comic.title }}</h1>
<h1>{{ comic.title if comic.title else '#' ~ comic.number }}</h1>
<p class="comic-date">{{ comic.date }}</p>
</div>
<div class="comic-image">
<img src="{{ url_for('static', filename='images/' + comic.filename) }}"
alt="{{ comic.title }}"
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
title="{{ comic.alt_text }}">
</div>
@@ -35,10 +35,10 @@
</div>
</div>
{% if comic.transcript %}
{% if comic.author_note %}
<div class="comic-transcript">
<h3>Transcript</h3>
<p>{{ comic.transcript }}</p>
<h3>Author Note</h3>
<p>{{ comic.author_note }}</p>
</div>
{% endif %}
</div>

View File

@@ -3,13 +3,13 @@
{% block content %}
<div class="comic-container">
<div class="comic-header">
<h1>{{ comic.title }}</h1>
<h1>{{ comic.title if comic.title else '#' ~ comic.number }}</h1>
<p class="comic-date">{{ comic.date }}</p>
</div>
<div class="comic-image">
<img src="{{ url_for('static', filename='images/' + comic.filename) }}"
alt="{{ comic.title }}"
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
title="{{ comic.alt_text }}">
</div>
@@ -35,10 +35,10 @@
</div>
</div>
{% if comic.transcript %}
{% if comic.author_note %}
<div class="comic-transcript">
<h3>Transcript</h3>
<p>{{ comic.transcript }}</p>
<h3>Author Note</h3>
<p>{{ comic.author_note }}</p>
</div>
{% endif %}
</div>