1 # Mattermost Bot module.
2 # Copyright (c) 2016-2022 by Someone <someone@somenet.org> (aka. Jan Vales <jan@jvales.net>)
3 # published under MIT-License
5 from inspect import cleandoc
11 # pylint: disable=wrong-import-position
12 from AbstractCommand import AbstractCommand
13 class DialogManagedCourseFeedback(AbstractCommand):
14 TRIGGER = "course-feedback"
15 CONFIG = {"display_name": "somebot-command", "auto_complete": True,
16 "auto_complete_hint": "['--help']",
18 CONFIG["auto_complete_desc"] = CONFIG["description"] = AbstractCommand.ICON_PRIVATE+"Run in course-channel. Opens dialog to edit/delete course-feedback."
21 def __init__(self, team_id, datadir):
22 super().__init__(team_id)
24 self.datadir = datadir
27 def on_POST(self, request, data):
28 if re.match(r"^(-|—|–)+help$", data["text"]):
29 request.respond_cmd_temp(cleandoc("""
30 ## :pencil:``Course feedback!``:rocket:
31 We want your feedback in order to find out which courses need to be improved asap to achieve the excellence we are accustomed to, or better.
32 The feedback will be anonymized during aggregation, then analyzed and discussed with the appropriate people like the course admins, the deans of study affairs and the vice rector for teaching matters and/or the in-house lawyers.
35 + Feedback for this course.
36 + How much time did you spent on this course.
37 + How did you like the modalities of this course? (Would you want it to be applied to others?)
38 + This course's modalities - describe them in a few words. (Also consider updating the info in VoWi - its a work resource for us and we use it to represent you)
39 + Feedback about this survey for :fsinf:. (This will not be shared outside of FSInf)
41 :information_source: *We are your legaly appointed representatives - we will never forward any personal info about you without your explicit permission.* :)
45 c = self.bot.api.get_channel(data["channel_id"])
47 #if c["type"] != 'O' or c["name"] in ["town-square", "off-topic"] or c["display_name"][0] == "=":
48 # request.respond_cmd_err("``/"+self.TRIGGER+"`` must be run in a course-channel.")
51 self._open_dialog(request, data)
52 request.respond_cmd_temp("## :white_check_mark: Success! :)\n#### Opened dialog.")
55 def on_POST_interactive(self, request, data):
56 self._open_dialog(request, data)
60 def on_POST_dialog(self, request, data):
62 print("on_POST_dialog")
65 if data["submission"]["feedback_hours"] and int(data["submission"]["feedback_hours"]) < 0:
66 request.respond(200, {"errors": {"feedback_hours": "Hours must be positive."}})
69 if data["submission"]["feedback_hours"] and int(data["submission"]["feedback_hours"]) > 4464:
70 request.respond(200, {"errors": {"feedback_hours": "Hours must be smaller than 4465. Did you really spend EVERY HOUR of the semester for this course? Did you not sleep at all?"}})
74 c = self.bot.api.get_channel(data["channel_id"])
76 self._response_store(self.datadir+data["callback_id"], "-feedback_distance.txt", data["submission"]["feedback_distance"], c["name"])
77 self._response_store(self.datadir+data["callback_id"], "-feedback_course.txt", data["submission"]["feedback_course"], c["name"])
78 self._response_store(self.datadir+data["callback_id"], "-feedback_hours.txt", data["submission"]["feedback_hours"], c["name"])
79 self._response_store(self.datadir+data["callback_id"], "-feedback_modus.txt", data["submission"]["feedback_modus"], c["name"])
80 self._response_store(self.datadir+data["callback_id"], "-feedback_modus_like.txt", data["submission"]["feedback_modus_like"], c["name"])
81 self._response_store(self.datadir+data["callback_id"], "-feedback_fsinf.txt", data["submission"]["feedback_fsinf"], c["name"])
83 request.respond(200, {})
86 def _open_dialog(self, request, data):
88 #print("on_POST_interactive")
91 callback_id = "res-"+data["team_id"]+"-"+data["channel_id"]+"-"+data["user_id"]
93 feedback_distance = self._response_load(self.datadir+callback_id, "-feedback_distance.txt")
94 feedback_course = self._response_load(self.datadir+callback_id, "-feedback_course.txt")
95 feedback_hours = self._response_load(self.datadir+callback_id, "-feedback_hours.txt")
96 feedback_modus = self._response_load(self.datadir+callback_id, "-feedback_modus.txt")
97 feedback_modus_like = self._response_load(self.datadir+callback_id, "-feedback_modus_like.txt", "0")
98 feedback_fsinf = self._response_load(self.datadir+callback_id, "-feedback_fsinf.txt")
101 "callback_id": callback_id,
102 "title": "Course feedback",
103 "submit_label":"Submit",
105 "display_name": "Was there an online option? Was it possible to complete the course only online? What did you think about the online option? (Max. 3000 characters)",
106 "placeholder": "Type here. Max. 3000 characters.\n+ Was it communicated?\n+ bla?\n+ bla?",
107 "name": "feedback_distance",
109 "help_text": "All your imput on all questions will be anonymized during aggregation. Aggregated input will be analyzed by FSInf and further used/forwarded to the course admins, the deans of study affairs, the vice rector for teaching and possibly others that are deemed able to fix things. You can edit/clear it at any time.",
111 "default": feedback_distance
113 "display_name": "How many hours did you invest into this course?",
114 "placeholder": "Hours. Positive integer.",
115 "name": "feedback_hours",
119 "default": feedback_hours
121 "display_name": "Describe the modalities (issues encountered and possible improvements) in a few words (Max. 3000 characters)",
122 "placeholder": "Type here. Max. 3000 characters.\n+ What was it? \n+ Were deadlines announced in a timely manner?\n+ Was the grading surprising?\n+ Random changes during the semester?",
123 "name": "feedback_modus",
126 "default": feedback_modus
128 "display_name": "How did you like the modalities of this course? (Do you want it to be applied to others?)",
129 "placeholder": "Type here. Max. 3000 characters.",
130 "name": "feedback_modus_like",
133 {"text": "I loved it", "value": "2" },
134 {"text": "I liked it", "value": "1" },
135 {"text": "I'm indifferent/Don't want to answer (default)", "value": "0" },
136 {"text": "I disliked it", "value": "-1" },
137 {"text": "I hated it", "value": "-2" },
140 "default": feedback_modus_like
142 "display_name": "Your Comment/Feedback about the course (Max. 3000 characters)",
143 "placeholder": "Type here. Max. 3000 characters.\n+ What should be changed?\n+ What was unfair?\n+ What was really good?",
144 "name": "feedback_course",
147 "default": feedback_course
149 "display_name": "Feedback (about this survey) for FSInf (Max. 3000 characters)",
150 "placeholder": "Type here. Max. 3000 characters.",
151 "name": "feedback_fsinf",
153 "help_text": "Your input will be anonymized during aggregation. Aggregated input will be analyzed by FSInf. We will not forward this text to anyone. You can edit/clear it at any time.",
155 "default": feedback_fsinf
159 self.bot.api.open_dialog(data["trigger_id"], self.URL+"/dialog", dialog)
162 def _response_load(self, path, filename, default=""):
165 if os.path.isfile(path):
166 with open(path, "r") as f:
171 def _response_store(self, path, filename, data, channelname=""):
173 data = str(data).strip()
174 if data == "" or data == "None" or data == "0":
175 if os.path.isfile(path):
177 self.bot.debug_chan("``course-feedback::"+channelname+filename+"`` result deleted.")
179 with open(path, "w") as f:
181 self.bot.debug_chan("``course-feedback::"+channelname+filename+"`` result stored.\n```\n"+data+"\n```")