Compare commits

..

No commits in common. "main" and "wirechan-hotfix" have entirely different histories.

5 changed files with 54 additions and 85 deletions

View file

@ -1,57 +1,47 @@
# WireChan - Anonymous ImageBoard # wirechan
## Description imageboard written in python(flask)
WireChan is an anonymous imageboard built using the Flask framework and MongoDB as its database. It allows users to communicate on various topics without the risk of being identified, offering both anonymous and logged-in posting options.
### Features # overview
- Anonymous and logged-in posting
- Admin dashboard for moderation
- Minimal dependencies
- Minimalistic design
## Installation Instructions wirechan is an anonymous(optional registration) imageboard written in Flask framework using MongoDB as a database. It's designed to be used
as a way of communication for various topics without the fear of being recogniszed, if the user wishes to remain unknown.
# features
>Both logged-in and anonymous posting
>Admin dashboard for moderation
>No Javascript whatsoever
>Minimal dependencies
>Minimalistic design
# installation
1. Clone the repository: 1. Clone the repository:
```
```bash
git clone https://git.lainlounge.xyz/hornet/wirechan git clone https://git.lainlounge.xyz/hornet/wirechan
``` ```
Create a virtual environment using venv: 2. Create and activate virtual environment:
```
```bash python3 -m venv venv && source venv/bin/activate
python3 -m venv env
``` ```
## Install the required dependencies: 3. Install the dependencies:
```
```bash python3 -m pip install -r requirements.txt
python3 -m pip install -r requirements.txt
``` ```
## Initialize MongoDB 4. Initialize the MongoDB server:
```
mongo #or systemctl enable mongod && systemctl start mongod
```
Start MongoDB by creating a new database via the MongoDB shell. 5. Start the server
Ensure the mongod service is running (for Windows, use mongo). ```
Start the Flask application in development mode: python3 app.py
```
```bash
flask run
```
Open your browser to view the created page at the specified URL.
## How To Use
Log in to your Dashboard instance with valid credentials at http://localhost:5000.
Create a new post by clicking the "Add a new post" button.
View or manage your posts by logging out and creating a new account if needed.
## Additional Features
Admin Dashboard: View profiles, posts, history, and moderation statuses.
Minimal Dependencies: Built-in Flask and MongoDB for ease of use.
Please note that WireChan is a work in progress, and there may be issues with the database or server configurations. Documentation will be updated as the project evolves.
## Important to know!
Wirechan doesnt provide the database to the project (yet).

55
app.py
View file

@ -1,25 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# ------------------------------------
# Wirechan was written by @hornet
# and represents a University project
# for his legitable proof of coding.
# (c) by hornetmaiden(hornet)
# Written in 2024
# ------------------------------------
import os
from flask import Flask, url_for, redirect, render_template, request, session, Response from flask import Flask, url_for, redirect, render_template, request, session, Response
from flask_wtf.csrf import CSRFProtect
from pymongo import MongoClient from pymongo import MongoClient
from datetime import datetime from datetime import datetime
from bson.objectid import ObjectId from bson.objectid import ObjectId
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__) app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', 'fallback_secret_key') #change this to a random string app.secret_key = 'secret_key' #change this to a random string
csrf = CSRFProtect(app)
#initialize the databases #initialize the databases
client = MongoClient('localhost', 27017) #change this if you are using a different host/port client = MongoClient('localhost', 27017) #change this if you are using a different host/port
@ -27,10 +13,7 @@ db = client.flask_db
posts_collection = db.posts_collection posts_collection = db.posts_collection
users_collection = db.users_collection users_collection = db.users_collection
nuke_counter = db.nuke_counter nuke_counter = db.nuke_counter
if session.get('username') == 'admin': # Safely check if the user is an admin isAdmin = False
isAdmin = True # Set isAdmin based on session
else:
isAdmin = False
#app routes #app routes
@app.route('/', methods=['GET']) @app.route('/', methods=['GET'])
@ -53,35 +36,37 @@ def board(board_name):
posts = posts_collection.find({'board_name': board_name}).sort('timestamp', -1) posts = posts_collection.find({'board_name': board_name}).sort('timestamp', -1)
display_name = next((link['display_name'] for link in links if link['name'] == board_name), board_name) display_name = next((link['display_name'] for link in links if link['name'] == board_name), board_name)
if session.get('username') == 'admin': if isAdmin == True or ('username' in session and session['username'] == 'admin'):
return render_template('board.html', title=board_name, header=display_name, links=links, posts=posts, admin=True) return render_template('board.html', title=board_name, header=display_name, links=links, posts=posts, admin=admin)
else: else:
return render_template('board.html', title=board_name, header=display_name, links=links, posts=posts, admin=None) return render_template('board.html', title=board_name, header=display_name, links=links, posts=posts, admin=None)
#posting API #posting API
@app.route('/post', methods=['POST']) @app.route('/post', methods=['POST'])
def post(): def post():
board_name = bleach.clean(request.form['board_name']) # Sanitize input board_name = request.form['board_name']
content = bleach.clean(request.form['content']) content = request.form['content']
if 'image' in request.files:
image = request.files['image'] if 'image' in request.files else None image = request.files['image']
else:
image = None
timestamp = datetime.now() timestamp = datetime.now()
username = session.get('username', 'Anonymous') # Use session for username if 'user_id' not in session:
username = 'Anonymous'
else:
username = session['username']
#insert the post into MongoDB
post_data = { post_data = {
'board_name': board_name, 'board_name': board_name,
'content': content, 'content': content,
'timestamp': timestamp, 'timestamp': timestamp,
'username': username 'username' : username
} }
if image and allowed_file(image.filename): if image != None:
post_data['image'] = image.read() post_data['image'] = image.read()
try: posts_collection.insert_one(post_data)
posts_collection.insert_one(post_data)
except Exception as e:
return f"Error inserting post: {e}", 500
return redirect(url_for('board', board_name=board_name)) return redirect(url_for('board', board_name=board_name))
#image API #image API
@ -104,12 +89,10 @@ def login_post():
user = users_collection.find_one({'username': username}) user = users_collection.find_one({'username': username})
if user and check_password_hash(user['password'], password): if user and check_password_hash(user['password'], password):
session.clear()
session['user_id'] = str(user['_id']) session['user_id'] = str(user['_id'])
session['username'] = username session['username'] = username
return redirect(url_for('index')) return redirect(url_for('index'))
elif user == 'admin' and check_password_hash(user['password'], password): elif user == 'admin' and check_password_hash(user['password'], password):
session.clear()
session['user_id'] = str(user['_id']) session['user_id'] = str(user['_id'])
session['username'] = 'admin' session['username'] = 'admin'
isAdmin = True isAdmin = True
@ -126,7 +109,7 @@ def register():
def register_post(): def register_post():
username = request.form['username'] username = request.form['username']
password = request.form['password'] password = request.form['password']
hashed_password = generate_password_hash(password, method='argon2') hashed_password = generate_password_hash(password, method='pbkdf2:sha256')
regalert = '' regalert = ''
if users_collection.find_one({'username': username}): if users_collection.find_one({'username': username}):

View file

@ -1,6 +1,4 @@
FlasK FlasK
Flask-WTF
bleach
bson
pymongo pymongo
bson
werkzeug werkzeug

View file

@ -8,7 +8,6 @@
<div class="link-container"> <div class="link-container">
<h1>login</h1> <h1>login</h1>
<form action="{{ url_for('login_post') }}" method="post"> <form action="{{ url_for('login_post') }}" method="post">
{{ csrf_token() }} <!-- Add this line to enable CSRF -->
<label for="username">username:</label> <label for="username">username:</label>
<input type="text" id="username" name="username" required> <input type="text" id="username" name="username" required>
<br> <br>

View file

@ -9,7 +9,6 @@
<h1>register</h1> <h1>register</h1>
<h4>{{ regalert }}</h4> <h4>{{ regalert }}</h4>
<form action="{{ url_for('register_post') }}" method="post"> <form action="{{ url_for('register_post') }}" method="post">
{{ csrf_token() }} <!-- Add this line to enable CSRF -->
<label for="username">username:</label> <label for="username">username:</label>
<input type="text" id="username" name="username" required> <input type="text" id="username" name="username" required>
<br> <br>