]> git.lizzy.rs Git - cheatdb.git/blob - app/views/threads.py
37ac3d1b7a59b1c57d0c19e2cfcf0b0a27065978
[cheatdb.git] / app / views / threads.py
1 # Content DB
2 # Copyright (C) 2018  rubenwardy
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17
18 from flask import *
19 from flask_user import *
20 from app import app
21 from app.models import *
22 from app.utils import triggerNotif, clearNotifications
23
24 from flask_wtf import FlaskForm
25 from wtforms import *
26 from wtforms.validators import *
27
28 @app.route("/threads/")
29 def threads_page():
30         query = Thread.query
31         if not Permission.SEE_THREAD.check(current_user):
32                 query = query.filter_by(private=False)
33         return render_template("threads/list.html", threads=query.all())
34
35
36 @app.route("/threads/<int:id>/subscribe/", methods=["POST"])
37 @login_required
38 def thread_subscribe_page(id):
39         thread = Thread.query.get(id)
40         if thread is None or not thread.checkPerm(current_user, Permission.SEE_THREAD):
41                 abort(404)
42
43         if current_user in thread.watchers:
44                 flash("Already subscribed!", "success")
45         else:
46                 flash("Subscribed to thread", "success")
47                 thread.watchers.append(current_user)
48                 db.session.commit()
49
50         return redirect(url_for("thread_page", id=id))
51
52
53 @app.route("/threads/<int:id>/unsubscribe/", methods=["POST"])
54 @login_required
55 def thread_unsubscribe_page(id):
56         thread = Thread.query.get(id)
57         if thread is None or not thread.checkPerm(current_user, Permission.SEE_THREAD):
58                 abort(404)
59
60         if current_user in thread.watchers:
61                 flash("Unsubscribed!", "success")
62                 thread.watchers.remove(current_user)
63                 db.session.commit()
64         else:
65                 flash("Not subscribed to thread", "success")
66
67         return redirect(url_for("thread_page", id=id))
68
69
70 @app.route("/threads/<int:id>/", methods=["GET", "POST"])
71 def thread_page(id):
72         clearNotifications(url_for("thread_page", id=id))
73
74         thread = Thread.query.get(id)
75         if thread is None or not thread.checkPerm(current_user, Permission.SEE_THREAD):
76                 abort(404)
77
78         if current_user.is_authenticated and request.method == "POST":
79                 comment = request.form["comment"]
80
81                 if len(comment) <= 500 and len(comment) > 3:
82                         reply = ThreadReply()
83                         reply.author = current_user
84                         reply.comment = comment
85                         db.session.add(reply)
86
87                         thread.replies.append(reply)
88                         if not current_user in thread.watchers:
89                                 thread.watchers.append(current_user)
90
91                         msg = None
92                         if thread.package is None:
93                                 msg = "New comment on '{}'".format(thread.title)
94                         else:
95                                 msg = "New comment on '{}' on package {}".format(thread.title, thread.package.title)
96
97
98                         for user in thread.watchers:
99                                 if user != current_user:
100                                         triggerNotif(user, current_user, msg, url_for("thread_page", id=thread.id))
101
102                         db.session.commit()
103
104                         return redirect(url_for("thread_page", id=id))
105
106                 else:
107                         flash("Comment needs to be between 3 and 500 characters.")
108
109         return render_template("threads/view.html", thread=thread)
110
111
112 class ThreadForm(FlaskForm):
113         title   = StringField("Title", [InputRequired(), Length(3,100)])
114         comment = TextAreaField("Comment", [InputRequired(), Length(10, 500)])
115         private = BooleanField("Private")
116         submit  = SubmitField("Open Thread")
117
118 @app.route("/threads/new/", methods=["GET", "POST"])
119 @login_required
120 def new_thread_page():
121         form = ThreadForm(formdata=request.form)
122
123         package = None
124         if "pid" in request.args:
125                 package = Package.query.get(int(request.args.get("pid")))
126                 if package is None:
127                         flash("Unable to find that package!", "error")
128
129         # Don't allow making threads on approved packages for now
130         if package is None:
131                 abort(403)
132
133         def_is_private   = request.args.get("private") or False
134         if not package.approved:
135                 def_is_private = True
136         allow_change     = package.approved
137         is_review_thread = package is not None and not package.approved
138
139         # Check that user can make the thread
140         if not package.checkPerm(current_user, Permission.CREATE_THREAD):
141                 flash("Unable to create thread!", "error")
142                 return redirect(url_for("home_page"))
143
144         # Only allow creating one thread when not approved
145         elif is_review_thread and package.review_thread is not None:
146                 flash("A review thread already exists!", "error")
147                 if request.method == "GET":
148                         return redirect(url_for("thread_page", id=package.review_thread.id))
149
150         # Set default values
151         elif request.method == "GET":
152                 form.private.data = def_is_private
153                 form.title.data   = request.args.get("title") or ""
154
155         # Validate and submit
156         elif request.method == "POST" and form.validate():
157                 thread = Thread()
158                 thread.author  = current_user
159                 thread.title   = form.title.data
160                 thread.private = form.private.data if allow_change else def_is_private
161                 thread.package = package
162                 db.session.add(thread)
163
164                 thread.watchers.append(current_user)
165                 if package is not None and package.author != current_user:
166                         thread.watchers.append(package.author)
167
168                 reply = ThreadReply()
169                 reply.thread  = thread
170                 reply.author  = current_user
171                 reply.comment = form.comment.data
172                 db.session.add(reply)
173
174                 thread.replies.append(reply)
175
176                 db.session.commit()
177
178                 if is_review_thread:
179                         package.review_thread = thread
180
181                 if package is not None:
182                         triggerNotif(package.author, current_user,
183                                         "New thread '{}' on package {}".format(thread.title, package.title), url_for("thread_page", id=thread.id))
184
185                 db.session.commit()
186
187                 return redirect(url_for("thread_page", id=thread.id))
188
189
190         return render_template("threads/new.html", form=form, allow_private_change=allow_change)