Compare commits
8 Commits
6a53088f50
...
c7cd40f5a9
| Author | SHA1 | Date | |
|---|---|---|---|
| c7cd40f5a9 | |||
| 68bfb237df | |||
| 8f378b817e | |||
| 368a7f57a4 | |||
| b0987ceff3 | |||
| be8ea1c34f | |||
| 0d229fd442 | |||
| b8a75571a5 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,5 @@
|
||||
.idea
|
||||
.venv
|
||||
|
||||
# This should be generated on deploy
|
||||
static/feed.rss
|
||||
29
app.py
29
app.py
@@ -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
27
comics_data.py
Normal 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
56
scripts/add_comic.py
Executable 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
97
scripts/generate_rss.py
Executable 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()
|
||||
@@ -183,7 +183,6 @@ main {
|
||||
.comic-image {
|
||||
text-align: center;
|
||||
margin-bottom: 1.5rem;
|
||||
border: 2px solid #000;
|
||||
padding: 0.5rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user