Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
539cc4d
Every post is private now
angelikabrown Mar 28, 2025
962778b
A profile page you can view if logged in.
jwheller0013 Mar 29, 2025
16c23e5
attempt 2
jwheller0013 Mar 29, 2025
5b15909
getting somewhere
KunleAdeyanju Mar 29, 2025
8af0311
Able to get markdown formatting to show up on posts
Isiah-A Mar 29, 2025
9e14d37
Change password button
jwheller0013 Mar 29, 2025
f34d779
Fixed flash for password
jwheller0013 Mar 30, 2025
1f9840f
replies working properly updated profile to show too
jwheller0013 Mar 30, 2025
86323d9
Add files via upload
Isiah-A Mar 30, 2025
434e42f
Every post is private now
angelikabrown Mar 31, 2025
46019dd
Changed name
jwheller0013 Mar 31, 2025
2ffe668
background color changed
KunleAdeyanju Mar 31, 2025
4eedd8f
Merge pull request #1 from ZCWDataSixZero/Kunle
KunleAdeyanju Mar 31, 2025
b4ac964
Merge remote-tracking branch 'origin/Isiah' into Isiah
Isiah-A Mar 31, 2025
fcc52e9
Merge branch 'dev' into James
jwheller0013 Mar 31, 2025
925c7e7
Merge pull request #2 from ZCWDataSixZero/James
jwheller0013 Mar 31, 2025
ab1889d
Delete CircusCircus directory
Isiah-A Mar 31, 2025
19c9484
Merge branch 'dev' into Angelika
angelikabrown Mar 31, 2025
0d1b090
Merge pull request #5 from ZCWDataSixZero/Angelika
angelikabrown Mar 31, 2025
481d0c2
Cleaning up errors
jwheller0013 Mar 31, 2025
15aa4f6
Fixed issues with comment windows
jwheller0013 Mar 31, 2025
5bd4970
Fixed issue with logout
jwheller0013 Mar 31, 2025
7af5ffd
Working on messages
jwheller0013 Mar 31, 2025
7f5c9f9
Merge branch 'dev' into Isiah
Isiah-A Mar 31, 2025
e2930ef
Merge pull request #6 from ZCWDataSixZero/Isiah
Isiah-A Mar 31, 2025
bf7bf11
Removed message link
angelikabrown Mar 31, 2025
afcb369
Merge pull request #7 from ZCWDataSixZero/dev
angelikabrown Apr 4, 2025
cb4e0d6
yup
angelikabrown Apr 4, 2025
9ec47ba
thing
angelikabrown Apr 4, 2025
a37261b
Some progress
angelikabrown Apr 5, 2025
b2a3103
Chat functionality
angelikabrown Apr 6, 2025
252f46c
setting up the rooms
angelikabrown Apr 7, 2025
fe30d43
working chat
angelikabrown Apr 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion .idea/CircusCircus.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added forum/.DS_Store
Binary file not shown.
3 changes: 3 additions & 0 deletions forum/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import socketio
from flask import Flask
from forum.routes import rt



def create_app():
"""Construct the core application."""
app = Flask(__name__, instance_relative_config=False)
Expand Down
114 changes: 84 additions & 30 deletions forum/app.py
Original file line number Diff line number Diff line change
@@ -1,57 +1,111 @@

from flask import render_template
from flask import render_template, session
from flask_login import LoginManager
from forum.models import Subforum, db, User
from flask_socketio import SocketIO

from . import create_app
app = create_app()
socketio = SocketIO(app)

app.config['SITE_NAME'] = 'Schooner'
app.config['SITE_DESCRIPTION'] = 'a schooner forum'

app.config['SITE_NAME'] = 'Something, Anything, that is not that'
app.config['SITE_DESCRIPTION'] = 'a forum for Data to learn from'
app.config['FLASK_DEBUG'] = 1

if __name__ == '__main__':
socketio.run(app,port=5555, debug=True)

def init_site():
print("creating initial subforums")
admin = add_subforum("Forum", "Announcements, bug reports, and general discussion about the forum belongs here")
add_subforum("Announcements", "View forum announcements here",admin)
add_subforum("Bug Reports", "Report bugs with the forum here", admin)
add_subforum("General Discussion", "Use this subforum to post anything you want")
add_subforum("Other", "Discuss other things here")
print("creating initial subforums")
admin = add_subforum("Forum", "Announcements, bug reports, and general discussion about the forum belongs here")
add_subforum("Announcements", "View forum announcements here",admin)
add_subforum("Bug Reports", "Report bugs with the forum here", admin)
add_subforum("General Discussion", "Use this subforum to post anything you want")
add_subforum("Other", "Discuss other things here")


def add_subforum(title, description, parent=None):
sub = Subforum(title, description)
if parent:
for subforum in parent.subforums:
if subforum.title == title:
return
parent.subforums.append(sub)
else:
subforums = Subforum.query.filter(Subforum.parent_id == None).all()
for subforum in subforums:
if subforum.title == title:
return
db.session.add(sub)
print("adding " + title)
db.session.commit()
return sub
sub = Subforum(title, description)
if parent:
for subforum in parent.subforums:
if subforum.title == title:
return
parent.subforums.append(sub)
else:
subforums = Subforum.query.filter(Subforum.parent_id == None).all()
for subforum in subforums:
if subforum.title == title:
return
db.session.add(sub)
print("adding " + title)
db.session.commit()
return sub

login_manager = LoginManager()
login_manager.init_app(app)

@login_manager.user_loader
def load_user(userid):
return User.query.get(userid)
return User.query.get(userid)

with app.app_context():
db.create_all() # TODO this may be redundant
if not Subforum.query.all():
init_site()
db.create_all() # TODO this may be redundant
if not Subforum.query.all():
init_site()

@app.route('/')
def index():
subforums = Subforum.query.filter(Subforum.parent_id == None).order_by(Subforum.id)
return render_template("subforums.html", subforums=subforums)
subforums = Subforum.query.filter(Subforum.parent_id == None).order_by(Subforum.id)
return render_template("subforums.html", subforums=subforums)



def messageReceived(methods=['GET', 'POST']):
print('message was received!!!')

@socketio.on('my event')
def handle_my_custom_event(json, methods=['GET', 'POST']):
print('received my event: ' + str(json))
socketio.emit('my response', json, callback=messageReceived)

# @socketio.on('connect')
# def handle_connect():
# username = session.get('username')
# room = session.get('room')
# if username is None or room is None:
# return
# if room not in rooms:
# leave_room(room)
# join_room(room)
# send({
# "sender": "",
# "message": f"{username} has entered the chat"
# }, to=room)
# rooms[room]["members"] += 1
#
# @socketio.on('message')
# def handle_message(payload):
# room = session.get('room')
# name = session.get('name')
# if room not in rooms:
# return
# message = {
# "sender": name,
# "message": payload["message"]
# }
# send(message, to=room)
# rooms[room]["messages"].append(message)
# @socketio.on('disconnect')
# def handle_disconnect():
# room = session.get("room")
# name = session.get("name")
# leave_room(room)
# if room in rooms:
# rooms[room]["members"] -= 1
# if rooms[room]["members"] <= 0:
# del rooms[room]
# send({
# "message": f"{name} has left the chat",
# "sender": ""
# }, to=room)
78 changes: 63 additions & 15 deletions forum/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
import datetime
import markdown

# create db here so it can be imported (with the models) into the App object.
from flask_sqlalchemy import SQLAlchemy
Expand All @@ -18,6 +19,7 @@ class User(UserMixin, db.Model):
posts = db.relationship("Post", backref="user")
comments = db.relationship("Comment", backref="user")


def __init__(self, email, username, password):
self.email = email
self.username = username
Expand All @@ -34,6 +36,8 @@ class Post(db.Model):
subforum_id = db.Column(db.Integer, db.ForeignKey('subforum.id'))
postdate = db.Column(db.DateTime)



#cache stuff
lastcheck = None
savedresponce = None
Expand Down Expand Up @@ -80,12 +84,15 @@ def __init__(self, title, description):
self.title = title
self.description = description


class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text)
postdate = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
post_id = db.Column(db.Integer, db.ForeignKey("post.id"))
replies = db.relationship('Reply', backref='comment', cascade='all, delete-orphan')


lastcheck = None
savedresponce = None
Expand Down Expand Up @@ -115,27 +122,68 @@ def get_time_string(self):
self.savedresponce = "Just a moment ago!"
return self.savedresponce


class Reply(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text)
postdate = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
comment_id = db.Column(db.Integer, db.ForeignKey("comment.id"))

user = db.relationship('User', backref='replies')


lastcheck = None
savedresponce = None
def __init__(self, content, postdate, user_id, comment_id):
self.content = content
self.postdate = postdate
self.user_id = user_id
self.comment_id = comment_id
def get_time_string(self):
#this only needs to be calculated every so often, not for every request
#this can be a rudamentary chache
now = datetime.datetime.now()
if self.lastcheck is None or (now - self.lastcheck).total_seconds() > 30:
self.lastcheck = now
else:
return self.savedresponce

diff = now - self.postdate
seconds = diff.total_seconds()
if seconds / (60 * 60 * 24 * 30) > 1:
self.savedresponce = " " + str(int(seconds / (60 * 60 * 24 * 30))) + " months ago"
elif seconds / (60 * 60 * 24) > 1:
self.savedresponce = " " + str(int(seconds / (60* 60 * 24))) + " days ago"
elif seconds / (60 * 60) > 1:
self.savedresponce = " " + str(int(seconds / (60 * 60))) + " hours ago"
elif seconds / (60) > 1:
self.savedresponce = " " + str(int(seconds / 60)) + " minutes ago"
else:
self.savedresponce = "Just a moment ago!"
return self.savedresponce

def error(errormessage):
return "<b style=\"color: red;\">" + errormessage + "</b>"
return "<b style=\"color: red;\">" + errormessage + "</b>"

def generateLinkPath(subforumid):
links = []
subforum = Subforum.query.filter(Subforum.id == subforumid).first()
parent = Subforum.query.filter(Subforum.id == subforum.parent_id).first()
links.append("<a href=\"/subforum?sub=" + str(subforum.id) + "\">" + subforum.title + "</a>")
while parent is not None:
links.append("<a href=\"/subforum?sub=" + str(parent.id) + "\">" + parent.title + "</a>")
parent = Subforum.query.filter(Subforum.id == parent.parent_id).first()
links.append("<a href=\"/\">Forum Index</a>")
link = ""
for l in reversed(links):
link = link + " / " + l
return link
links = []
subforum = Subforum.query.filter(Subforum.id == subforumid).first()
parent = Subforum.query.filter(Subforum.id == subforum.parent_id).first()
links.append("<a href=\"/subforum?sub=" + str(subforum.id) + "\">" + subforum.title + "</a>")
while parent is not None:
links.append("<a href=\"/subforum?sub=" + str(parent.id) + "\">" + parent.title + "</a>")
parent = Subforum.query.filter(Subforum.id == parent.parent_id).first()
links.append("<a href=\"/\">Forum Index</a>")
link = ""
for l in reversed(links):
link = link + " / " + l
return link


#Post checks
def valid_title(title):
return len(title) > 4 and len(title) < 140
return len(title) > 4 and len(title) < 140
def valid_content(content):
return len(content) > 10 and len(content) < 5000
return len(content) > 10 and len(content) < 5000

Loading