initial commit
This commit is contained in:
commit
492b513885
4 changed files with 232 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
feeds/
|
||||
mock/
|
||||
venv/
|
||||
48
README.md
Normal file
48
README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# RSS GENERATOR
|
||||
This is an rss feed generator with a pseudo TUI interface. This was mainly created for people who are utilizing basic HTML to write a blog.
|
||||
|
||||
While, of course, experienced developers take this simplistic route, a majority of people who are just writing their blogs manually are new to web development. This application is intended to provide the newbies a way to easily generate an RSS feed. Think about the people on neocities or in the tildeverse.
|
||||
|
||||
Because this software is made for new web developer, I provide a very detailed explanation on how to "install" and "run" this "program" below. If you already know what to do, just clone the repo and run the code bruh.
|
||||
|
||||
__Capabilities:__
|
||||
1. Generate an RSS feed
|
||||
2. Add a post entry to an existing RSS feed
|
||||
3. List all post entries in TUI
|
||||
4. Edit a post entry
|
||||
5. Delete a post entry
|
||||
6. Only saves when you explicitly state, so bulk operation are possible.
|
||||
|
||||
|
||||
# Dependencies
|
||||
- python
|
||||
- git
|
||||
|
||||
__NOTE__ there are no third party packages used, so you do not need a virtual environment and you do not need to pip install anything!
|
||||
|
||||
|
||||
# How To
|
||||
1. Using the terminal, clone this repository into the base directory of your website.
|
||||
|
||||
`git clone https://git.domdit.com/dominic/rss-generator`
|
||||
|
||||
If you do not have git installed, you should install it on your system. If you cannot install it, you can copy the contents of `generator.py` and `config.py` into a new folder called `rss-generator` inside the base directory of your website.
|
||||
|
||||
__NOTE__ If you are cloning this repo inside an already existing git repo, consider adding this repo as a submodule instead `git submodule add https://git.domdit.com/dominic/rss-generator rss-generator`
|
||||
|
||||
2. Inside the `rss-generator` directory, there is a config file. You must fill out this config file. there are detailed instructions to follow along inside the config file.
|
||||
|
||||
3. Once the config file is filled out and saved, you can now run `python3 generator.py`
|
||||
|
||||
4. If this is the first time running it, it will generate a new rss feed for you and ask you to fill out information for your first (most recent) blog post
|
||||
|
||||
5. You will then be redirected to the action menu, if you just want to save, you can type the number 5 and hit enter.
|
||||
|
||||
6. You can also do other operations like see the list of all of your blog posts, edit a blog post rss entry, or delete a blog post rss entry
|
||||
|
||||
7. changes do not take place until you explicity his save. so if you mess up you can always quit without saving and start over.
|
||||
|
||||
8. Make sure your rss feed looks correct, and is where you want it. If you did not change XML_BASE_PATH, it will be in the base directory of your website
|
||||
|
||||
9. Now that you have an rss feed, make sure you link to it somewhere on your website so people can find it!
|
||||
|
||||
21
config.py
Normal file
21
config.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# ####YOU MUST FILL THESE OUT FOR THE GENERATOR TO WORK###################
|
||||
# Title of your website, shows in people's RSS feed
|
||||
TITLE = "国際面倒くさい"
|
||||
|
||||
# The URL to your website "https://www.yourwebsite.com"
|
||||
URL = "https://jumbo.subte.cc"
|
||||
|
||||
# Description of your website
|
||||
DESCRIPTION = "mumbling in japanese"
|
||||
|
||||
# Please link back to me :)
|
||||
GENERATOR = "https://www.domdit.com"
|
||||
|
||||
# Language of your website
|
||||
LANGUAGE = "en-us"
|
||||
|
||||
# if you want your rss feed somewhere else, like a subdir, specify that here
|
||||
# example: `feeds` would output your rss feed to www.yoursite.com/feeds/index.xml
|
||||
# if you leave it None it will be www.yourside.com/index.xml (recommended)
|
||||
XML_BASE_PATH = "feeds"
|
||||
# ########################################################################
|
||||
160
generator.py
Normal file
160
generator.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import platform
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from config import TITLE, URL, DESCRIPTION, GENERATOR, LANGUAGE, XML_BASE_PATH
|
||||
|
||||
|
||||
class RSSGenerator:
|
||||
ATOM_NAMESPACE = "HTTP://WWW.W3.ORG/2005/ATOM"
|
||||
|
||||
def __init__(self):
|
||||
self.now = datetime.now().strftime("%a, %d %b %Y %H:%M:%S %z")
|
||||
|
||||
self.output_path = f"../{XML_BASE_PATH}/index.xml" if XML_BASE_PATH else "../index.xml"
|
||||
|
||||
self.post_title = None
|
||||
self.post_link = None
|
||||
self.post_desc = None
|
||||
self.post_date = self.now
|
||||
|
||||
self.tree = None
|
||||
self.root = None
|
||||
self.channel = None
|
||||
|
||||
self.items = []
|
||||
|
||||
def main(self):
|
||||
self.clear()
|
||||
if os.path.exists(self.output_path):
|
||||
print('RSS feed exists, parsing...')
|
||||
self.tree = ET.parse(self.output_path)
|
||||
self.parse_existing_feed()
|
||||
self.action_screen()
|
||||
|
||||
else:
|
||||
print('RSS feed does not exist, generating a new one...')
|
||||
Path("/".join(self.output_path.split('/')[:-1])).mkdir(parents=True, exist_ok=True)
|
||||
self.generate_new_feed()
|
||||
self.request_new_post_details()
|
||||
self.push_new_post()
|
||||
self.tree = ET.ElementTree(self.root)
|
||||
self.action_screen()
|
||||
|
||||
def action_screen(self):
|
||||
result = input("\nWhat would you like to do? \n[1] Add a new entry [2] List all posts [3] Delete an entry\n[4] Edit an entry [5] Save [6] Quit Without Saving\nEnter number: ")
|
||||
self.clear()
|
||||
if int(result) == 1:
|
||||
self.request_new_post_details()
|
||||
self.push_new_post()
|
||||
self.action_screen()
|
||||
|
||||
if int(result) == 2:
|
||||
self.list_posts()
|
||||
self.action_screen()
|
||||
|
||||
elif int(result) == 3:
|
||||
self.delete_post()
|
||||
self.action_screen()
|
||||
|
||||
elif int(result) == 4:
|
||||
self.edit_post()
|
||||
self.action_screen()
|
||||
|
||||
elif int(result) == 5:
|
||||
self.tree.write(self.output_path, encoding='utf-8', xml_declaration=True)
|
||||
sys.exit(0)
|
||||
|
||||
elif int(result) == 6:
|
||||
sys.exit(0)
|
||||
else:
|
||||
print('Unknown Command!')
|
||||
self.action_screen()
|
||||
|
||||
def parse_existing_feed(self):
|
||||
self.root = self.tree.getroot()
|
||||
self.channel = self.root.find('channel')
|
||||
|
||||
def generate_new_feed(self):
|
||||
|
||||
self.root = ET.Element("rss", {"version": "2.0", "xmlns:atom": self.ATOM_NAMESPACE})
|
||||
|
||||
self.channel = ET.SubElement(self.root, "channel")
|
||||
title = ET.SubElement(self.channel, "title")
|
||||
title.text = TITLE
|
||||
|
||||
link = ET.SubElement(self.channel, "{http://www.w3.org/2005/Atom}link")
|
||||
link.set("rel", "self")
|
||||
link.set("href", f"{URL}/{self.output_path}")
|
||||
link.set("type", "application/atom+xml")
|
||||
|
||||
desc = ET.SubElement(self.channel, "description")
|
||||
desc.text = DESCRIPTION
|
||||
|
||||
generator = ET.SubElement(self.channel, "generator")
|
||||
generator.text = GENERATOR
|
||||
|
||||
lang = ET.SubElement(self.channel, "language")
|
||||
lang.text = LANGUAGE
|
||||
|
||||
def request_new_post_details(self):
|
||||
self.post_title = input("\nPost Title: ")
|
||||
self.post_link = input("Post Link: ")
|
||||
self.post_desc = input("Post Description: ")
|
||||
|
||||
def push_new_post(self):
|
||||
item = ET.SubElement(self.channel, 'item')
|
||||
|
||||
title = ET.SubElement(item, 'title')
|
||||
title.text = self.post_title
|
||||
|
||||
link = ET.SubElement(item, 'link')
|
||||
link.text = self.post_link
|
||||
|
||||
description = ET.SubElement(item, 'description')
|
||||
description.text = self.post_desc
|
||||
|
||||
def list_posts(self):
|
||||
print("\nHere is a list of all your posts:")
|
||||
for idx, item in enumerate(self.channel.findall('item')):
|
||||
title = item.find('title').text
|
||||
|
||||
print(f"[{idx}] {title}")
|
||||
|
||||
def delete_post(self):
|
||||
self.list_posts()
|
||||
|
||||
result = input("\nWhich post would you like to delete? Enter number: ")
|
||||
|
||||
for idx, item in enumerate(self.channel.findall('item')):
|
||||
if idx == int(result):
|
||||
self.channel.remove(item)
|
||||
|
||||
def edit_post(self):
|
||||
self.list_posts()
|
||||
|
||||
result = input("\nWhich post would you like to edit? Enter number: ")
|
||||
|
||||
self.request_new_post_details()
|
||||
|
||||
for idx, item in enumerate(self.channel.findall('item')):
|
||||
if idx == int(result):
|
||||
item.find('title').text = self.post_title
|
||||
item.find('description').text = self.post_desc
|
||||
item.find('link').text = self.post_link
|
||||
|
||||
def clear(self):
|
||||
system = platform.system().lower()
|
||||
if system == 'windows':
|
||||
subprocess.run('cls', shell=True)
|
||||
else:
|
||||
subprocess.run('clear', shell=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
rss = RSSGenerator()
|
||||
rss.main()
|
||||
Loading…
Reference in a new issue