commit 50402ded4b80df076c8bb7e8403093a8df2d768c Author: Benny Date: Wed Dec 24 07:30:23 2025 -0600 Buddy System Babyyyyy diff --git a/app.py b/app.py new file mode 100644 index 0000000..0616784 --- /dev/null +++ b/app.py @@ -0,0 +1,183 @@ + from flask import ( + Flask, render_template_string, request, redirect, url_for, flash, jsonify, + make_response, abort + ) + from flask_sqlalchemy import SQLAlchemy + from flask_login import ( + LoginManager, UserMixin, login_user, current_user, login_required, logout_user + ) + from werkzeug.security import generate_password_hash, check_password_hash + + +load_dotenv() + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///posts.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['UPLOAD_FOLDER'] = 'static/uploads' +app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY') + +db = SQLAlchemy(app) +login_manager = LoginManager(app) +login_manager.login_view = 'login' + +USERNAME = os.getenv('FLASK_LOGIN_USER') +PASSWORD = os.getenv('FLASK_LOGIN_PASSWORD') + +if not os.path.exists(app.config['UPLOAD_FOLDER']): + os.makedirs(app.config['UPLOAD_FOLDER']) + +class User(UserMixin): + id = 1 + +@login_manager.user_loader +def load_user(user_id): + if user_id == "1": + return User() + return None + +class BlogPost(db.Model): + id = db.Column(db.Integer, primary_key=True) + title = db.Column(db.String(255), nullable=False) + slug = db.Column(db.String(255), nullable=False) + content = db.Column(db.Text, nullable=False) + images = db.Column(db.Text, nullable=True) + category = db.Column(db.String(100), nullable=True) + tags = db.Column(db.Text, nullable=True) + pinned = db.Column(db.Boolean, default=False) + +with app.app_context(): + db.create_all() + + +app.template_filter('from_json') +def from_json(value): + try: + return json.loads(value) + except (TypeError, json.JSONDecodeError): + return [] + +@app.route("/login", methods=["GET", "POST"]) +def login(): + if request.method == "POST": + username = request.form["username"] + password = request.form["password"] + + if username == USERNAME and password == PASSWORD: + user = User() + login_user(user) + session.permanent = True + return redirect(url_for("admin_panel")) + + flash("Invalid email or password!", "danger") + return render_template("login.html") + +@app.route("/logout") +@login_required +def logout(): + logout_user() + return redirect(url_for("index")) + +@app.route('/newblog', methods=['GET', 'POST']) +@login_required +def new_blog(): + if request.method == 'POST': + title = request.form['title'] + content = request.form['content'].replace("\n", "
") + category = request.form['category'] + tags = request.form['tags'] + pinned = 'pinned' in request.form + images = request.files.getlist('images') + + slug = slugify(title) + image_filenames = [secure_filename(image.filename) for image in images if image.filename] + for image, filename in zip(images, image_filenames): + image.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) + + new_post = BlogPost( + title=title, + slug=slug, + content=content, + category=category, + tags=tags, + pinned=pinned, + images=json.dumps(image_filenames) + ) + db.session.add(new_post) + db.session.commit() + return redirect(url_for('blog')) + + return render_template('new_blog.html') + +@app.route('/edit-blog/', methods=['GET', 'POST']) +@login_required +def edit_blog(slug): + blogpost = BlogPost.query.filter_by(slug=slug).first_or_404() + + if request.method == 'POST': + blogpost.title = request.form['title'] + blogpost.slug = slugify(blogpost.title) + blogpost.content = request.form['content'].replace("\n", "
") + blogpost.category = request.form['category'] + blogpost.tags = request.form['tags'] + blogpost.pinned = 'pinned' in request.form + + images = request.files.getlist('images') + image_filenames = json.loads(blogpost.images) if blogpost.images else [] + + for image in images: + if image.filename: + filename = secure_filename(image.filename) + image.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) + image_filenames.append(filename) + + blogpost.images = json.dumps(image_filenames) + db.session.commit() + return redirect(url_for('view_blog', slug=blogpost.slug)) + + return render_template('edit_blog.html', blogpost=blogpost) + +@app.route('/delete-blog/', methods=['POST']) +@login_required +def delete_blog(slug): + blogpost = BlogPost.query.filter_by(slug=slug).first_or_404() + if blogpost.images: + for filename in json.loads(blogpost.images): + image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) + if os.path.exists(image_path): + os.remove(image_path) + db.session.delete(blogpost) + db.session.commit() + return redirect(url_for('admin_panel')) + + + +@app.route('/blogtag/') +def view_tag(tag): + tag_lower = tag.lower() # Normalize case + blogpost = BlogPost.query.filter(func.lower(BlogPost.tags).contains(tag_lower)).order_by(BlogPost.id.desc()).all() + return render_template('blog_tag_results.html', blogpost=blogpost, tag=tag) + +@app.route('/blog') +def blog(): + blogpost = BlogPost.query.order_by(BlogPost.id.desc()).all() + return render_template('blog.html', blogpost=blogpost) + +@app.route('/admin') +@login_required +def admin_panel(): + blogpost = BlogPost.query.order_by(BlogPost.id.desc()).all() + projectpost = ProjectPost.query.order_by(ProjectPost.id.desc()).all() + return render_template('admin.html', blogpost=blogpost) + +@app.route('/blog/') +def view_blog(slug): + blogpost = BlogPost.query.filter_by(slug=slug).first_or_404() + return render_template('view_blog.html', blogpost=blogpost) + +@app.route('/') +def index(): + return render_template('index.html') + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file