Add saved post support. Delete posts when new block is added.

This commit is contained in:
John Stephani 2025-12-27 23:10:57 -06:00
parent 7ecabdf2b7
commit cc96622c71
5 changed files with 107 additions and 17 deletions

View File

@ -1,6 +1,7 @@
from flask import Flask, send_file, render_template, request from flask import Flask, send_file, render_template, request
from urllib.parse import urlparse from urllib.parse import urlparse
import delete_posts
import config import config
import json import json
import re import re
@ -27,12 +28,32 @@ def hide_post(permalink):
post post
SET SET
hidden = ? hidden = ?
WHERE
permalink = ? AND
saved = ?
"""
binds = [True, permalink, False]
cursor.execute(update,binds)
connection.commit()
connection.close()
return ""
@app.route('/save/<path:permalink>')
def save_post(permalink):
if permalink[0] != "/":
permalink = "/" + permalink
connection = sqlite3.connect(config.db_file)
cursor = connection.cursor()
action = request.args.get("action")
update = """
UPDATE
post
SET
saved = ?
WHERE WHERE
permalink = ? permalink = ?
""" """
binds = [True, permalink] binds = [(action == "save"), permalink]
print(update)
print(binds)
cursor.execute(update,binds) cursor.execute(update,binds)
connection.commit() connection.commit()
connection.close() connection.close()
@ -115,6 +136,7 @@ def admin():
return "" return ""
cursor.execute(upsert, binds) cursor.execute(upsert, binds)
connection.commit() connection.commit()
delete_posts.run()
sidebar_links = get_sidebar_links(cursor) sidebar_links = get_sidebar_links(cursor)
select = """ select = """
SELECT SELECT
@ -149,12 +171,13 @@ def front_page():
FROM FROM
post post
WHERE WHERE
hidden = ? hidden = ? AND
saved = ?
ORDER BY ORDER BY
score desc score desc
LIMIT ? LIMIT ?
""" """
binds = [False, config.posts_per_page_load] binds = [False, False, config.posts_per_page_load]
posts = get_posts_from_select(cursor, select, binds) posts = get_posts_from_select(cursor, select, binds)
connection.close() connection.close()
return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links) return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links)
@ -184,7 +207,8 @@ def other_page():
FROM FROM
post post
WHERE WHERE
hidden = ? hidden = ? AND
saved = ?
GROUP BY GROUP BY
subreddit subreddit
) t ) t
@ -195,11 +219,34 @@ def other_page():
score desc score desc
LIMIT ? LIMIT ?
""" """
binds = [False, False, config.other_posts_cutoff, config.posts_per_page_load] binds = [False, False, False, config.other_posts_cutoff, config.posts_per_page_load]
posts = get_posts_from_select(cursor, select, binds) posts = get_posts_from_select(cursor, select, binds)
connection.close() connection.close()
return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links) return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links)
@app.route('/r/saved')
def get_saved():
title = "/r/saved"
connection = sqlite3.connect(config.db_file)
cursor = connection.cursor()
sidebar_links = get_sidebar_links(cursor)
select = """
SELECT
post
FROM
post
WHERE
saved = ?
ORDER BY
score desc
LIMIT ?
"""
binds = [True, config.posts_per_page_load]
posts = get_posts_from_select(cursor, select, binds)
connection.close()
return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links, saved=True)
@app.route('/r/<path:subreddit>') @app.route('/r/<path:subreddit>')
def get_subreddit(subreddit): def get_subreddit(subreddit):
title = f"/r/{subreddit}" title = f"/r/{subreddit}"
@ -213,12 +260,13 @@ def get_subreddit(subreddit):
post post
WHERE WHERE
subreddit = ? AND subreddit = ? AND
hidden = ? hidden = ? AND
saved = ?
ORDER BY ORDER BY
score desc score desc
LIMIT ? LIMIT ?
""" """
binds = [subreddit, False, config.posts_per_page_load] binds = [subreddit, False, False, config.posts_per_page_load]
posts = get_posts_from_select(cursor, select, binds) posts = get_posts_from_select(cursor, select, binds)
connection.close() connection.close()
return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links) return render_template('index.html', title=title, posts=posts, sidebar_links=sidebar_links)
@ -249,6 +297,7 @@ def get_sidebar_links(cursor):
links = [f"/r/{sub[0]}" for sub in results] links = [f"/r/{sub[0]}" for sub in results]
links.insert(0, "/r/all") links.insert(0, "/r/all")
links.append("/r/other") links.append("/r/other")
links.append("/r/saved")
links.append("/admin") links.append("/admin")
return links return links

View File

@ -10,14 +10,22 @@ def run():
now = int(time.time()) now = int(time.time())
max_created_utc = now - config.max_age_seconds max_created_utc = now - config.max_age_seconds
print("Deleting old posts") print("Deleting old posts")
delete = "DELETE FROM post WHERE created_utc < ?" delete = "DELETE FROM post WHERE created_utc < ? AND saved = ?"
binds = [max_created_utc] binds = [max_created_utc, False]
cursor.execute(delete, binds) cursor.execute(delete, binds)
print("Deleting posts from blocked subreddits") print("Deleting posts from blocked subreddits")
select = "SELECT name FROM block WHERE name like '/r/%'" select = "SELECT name FROM block WHERE name like '/r/%'"
binds = [row[0][3:] for row in cursor.execute(select).fetchall()] binds = [row[0][3:] for row in cursor.execute(select).fetchall()]
bind_array = ",".join(["?"]*len(binds)) bind_array = ",".join(["?"]*len(binds))
delete = f"DELETE FROM post WHERE subreddit IN ({bind_array})" binds.append(False)
delete = f"DELETE FROM post WHERE subreddit IN ({bind_array}) AND saved = ?"
cursor.execute(delete, binds)
print("Deleting posts from blocked users")
select = "SELECT name FROM block WHERE name like '/u/%'"
binds = [row[0][3:] for row in cursor.execute(select).fetchall()]
bind_array = ",".join(["?"]*len(binds))
binds.append(False)
delete = f"DELETE FROM post WHERE author IN ({bind_array}) AND saved = ?"
cursor.execute(delete, binds) cursor.execute(delete, binds)
print("Deleting old media db rows") print("Deleting old media db rows")
delete = "DELETE FROM media WHERE permalink NOT IN (SELECT permalink FROM post)" delete = "DELETE FROM media WHERE permalink NOT IN (SELECT permalink FROM post)"

View File

@ -6,7 +6,7 @@ import sqlite3
os.makedirs(config.db_dir, exist_ok=True) os.makedirs(config.db_dir, exist_ok=True)
connection = sqlite3.connect(config.db_file) connection = sqlite3.connect(config.db_file)
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS post(permalink primary key, subreddit, created_utc, score, media_fetched, post, hidden)") cursor.execute("CREATE TABLE IF NOT EXISTS post(permalink primary key, subreddit, author, created_utc, score, media_fetched, post, hidden, saved)")
cursor.execute("CREATE TABLE IF NOT EXISTS media(permalink, url , local, PRIMARY KEY (permalink, url))") cursor.execute("CREATE TABLE IF NOT EXISTS media(permalink, url , local, PRIMARY KEY (permalink, url))")
cursor.execute("CREATE TABLE IF NOT EXISTS subreddit(subreddit primary key, minimum_score, fetch_by, fetch_max)") cursor.execute("CREATE TABLE IF NOT EXISTS subreddit(subreddit primary key, minimum_score, fetch_by, fetch_max)")
cursor.execute("CREATE TABLE IF NOT EXISTS block(name primary key)") cursor.execute("CREATE TABLE IF NOT EXISTS block(name primary key)")

View File

@ -57,8 +57,8 @@ def scrape_subreddit_data(subreddit, minimum_score=100, pull_by="day", limit=5,
def save_posts_to_db(data, cursor): def save_posts_to_db(data, cursor):
if len(data)==0: if len(data)==0:
return return
upsert = "INSERT INTO post(permalink, subreddit, created_utc, score, media_fetched, post, hidden) VALUES " upsert = "INSERT INTO post(permalink, subreddit, created_utc, score, media_fetched, post, hidden, saved, author) VALUES "
upsert += ",".join(["(?,?,?,?,?,?,?)"] * len(data)) upsert += ",".join(["(?,?,?,?,?,?,?,?,?)"] * len(data))
upsert += " ON CONFLICT(permalink) DO UPDATE SET score=excluded.score, post=excluded.post" upsert += " ON CONFLICT(permalink) DO UPDATE SET score=excluded.score, post=excluded.post"
binds = [] binds = []
for post in data: for post in data:
@ -69,6 +69,8 @@ def save_posts_to_db(data, cursor):
binds.append(False) binds.append(False)
binds.append(json.dumps(post)) binds.append(json.dumps(post))
binds.append(False) binds.append(False)
binds.append(False)
binds.append(post["author"])
cursor.execute(upsert, binds) cursor.execute(upsert, binds)
def download_media(cursor): def download_media(cursor):

View File

@ -10,6 +10,7 @@
--darker: #171717; --darker: #171717;
--light: #bfbfbf; --light: #bfbfbf;
--confirm: #970000; --confirm: #970000;
--saved: #9f9400;
} }
html { html {
height: 100%; height: 100%;
@ -139,6 +140,9 @@
.button-wrapper button.confirm { .button-wrapper button.confirm {
background-color: var(--confirm) background-color: var(--confirm)
} }
.button-wrapper button.saved {
background-color: var(--saved)
}
.button-wrapper button.gallery { .button-wrapper button.gallery {
padding: 5px; padding: 5px;
background-color: var(--darker); background-color: var(--darker);
@ -211,8 +215,9 @@
</div> </div>
{% endif %} {% endif %}
<span class="button-wrapper"> <span class="button-wrapper">
<button type="button" onpointerdown='commentsDown(this, "{{ post.permalink }}")' onpointerup='commentsUp(this, "{{ post.permalink }}")'>Comments</button> <button type="button" name="comments" onpointerdown='commentsDown(this, "{{ post.permalink }}")' onpointerup='commentsUp(this, "{{ post.permalink }}")'>Comments</button>
<button type="button" onclick='hide(this, "{{ post.permalink }}")'>Hide</button> <button type="button" name="save" onclick='save(this, "{{ post.permalink }}")' {% if saved %}class='saved'{% endif %}>Save</button>
<button type="button" name="hide" onclick='hide(this, "{{ post.permalink }}")'>Hide</button>
</span> </span>
</div> </div>
{% endfor %} {% endfor %}
@ -284,6 +289,11 @@
// main button code // main button code
function hide(button, permalink){ function hide(button, permalink){
div = button.closest('.post');
hideButton = div.querySelector('[name="save"]');
if (hideButton.classList.contains('saved')){
return;
}
if (button.classList.contains('confirm')) { if (button.classList.contains('confirm')) {
div = button.closest('.post'); div = button.closest('.post');
div.remove(); div.remove();
@ -319,6 +329,27 @@
}, 500); }, 500);
} }
} }
function save(button, permalink) {
if (button.classList.contains("saved")) {
button.classList.remove("saved");
try {
fetch('/save' + permalink + '?action=unsave');
} catch (error) {
console.error('Could not unsave', error);
}
} else {
button.classList.add("saved");
div = button.closest('.post');
hideButton = div.querySelector('[name="hide"]');
hideButton.classList.remove("confirm");
try {
fetch('/save' + permalink + '?action=save');
} catch (error) {
console.error('Could not save', error);
}
}
}
// text expand code // text expand code
function checkHeight(){ function checkHeight(){