| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  | __filename__ = "question.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2021-01-26 10:07:42 +00:00
										 |  |  | __version__ = "1.2.0" | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							| 
									
										
										
										
											2021-09-10 16:14:50 +00:00
										 |  |  | __email__ = "bob@libreserver.org" | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-15 15:08:12 +00:00
										 |  |  | __module_group__ = "ActivityPub" | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-12-26 20:36:08 +00:00
										 |  |  | from utils import locate_post | 
					
						
							| 
									
										
										
										
											2021-12-26 15:13:34 +00:00
										 |  |  | from utils import load_json | 
					
						
							| 
									
										
										
										
											2021-12-26 14:47:21 +00:00
										 |  |  | from utils import save_json | 
					
						
							| 
									
										
										
										
											2021-12-26 10:57:03 +00:00
										 |  |  | from utils import has_object_dict | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  | def questionUpdateVotes(base_dir: str, nickname: str, domain: str, | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |                         replyJson: {}) -> ({}, str): | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     """ For a given reply update the votes on a question
 | 
					
						
							| 
									
										
										
										
											2019-11-29 19:22:11 +00:00
										 |  |  |     Returns the question json object if the vote totals were changed | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-26 10:57:03 +00:00
										 |  |  |     if not has_object_dict(replyJson): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not replyJson['object'].get('inReplyTo'): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not replyJson['object']['inReplyTo']: | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2020-08-28 14:45:07 +00:00
										 |  |  |     if not isinstance(replyJson['object']['inReplyTo'], str): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2020-01-30 10:11:08 +00:00
										 |  |  |     if not replyJson['object'].get('name'): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |     inReplyTo = replyJson['object']['inReplyTo'] | 
					
						
							| 
									
										
										
										
											2021-12-26 20:36:08 +00:00
										 |  |  |     questionPostFilename = locate_post(base_dir, nickname, domain, inReplyTo) | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not questionPostFilename: | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2021-12-26 15:13:34 +00:00
										 |  |  |     questionJson = load_json(questionPostFilename) | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not questionJson: | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2021-12-26 10:57:03 +00:00
										 |  |  |     if not has_object_dict(questionJson): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not questionJson['object'].get('type'): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |     if questionJson['type'] != 'Question': | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not questionJson['object'].get('oneOf'): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not isinstance(questionJson['object']['oneOf'], list): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:50:08 +00:00
										 |  |  |     if not questionJson['object'].get('content'): | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |     replyVote = replyJson['object']['name'] | 
					
						
							| 
									
										
										
										
											2020-01-30 10:11:08 +00:00
										 |  |  |     # does the reply name field match any possible question option? | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |     foundAnswer = None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     for possibleAnswer in questionJson['object']['oneOf']: | 
					
						
							|  |  |  |         if not possibleAnswer.get('name'): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2020-01-30 10:11:08 +00:00
										 |  |  |         if possibleAnswer['name'] == replyVote: | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |             foundAnswer = possibleAnswer | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |             break | 
					
						
							|  |  |  |     if not foundAnswer: | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     # update the voters file | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |     votersFileSeparator = ';;;' | 
					
						
							|  |  |  |     votersFilename = questionPostFilename.replace('.json', '.voters') | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     if not os.path.isfile(votersFilename): | 
					
						
							|  |  |  |         # create a new voters file | 
					
						
							| 
									
										
										
										
											2021-06-22 12:27:10 +00:00
										 |  |  |         with open(votersFilename, 'w+') as votersFile: | 
					
						
							| 
									
										
										
										
											2021-06-21 22:53:04 +00:00
										 |  |  |             votersFile.write(replyJson['actor'] + | 
					
						
							|  |  |  |                              votersFileSeparator + | 
					
						
							|  |  |  |                              foundAnswer + '\n') | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         if replyJson['actor'] not in open(votersFilename).read(): | 
					
						
							|  |  |  |             # append to the voters file | 
					
						
							| 
									
										
										
										
											2021-06-22 12:27:10 +00:00
										 |  |  |             with open(votersFilename, 'a+') as votersFile: | 
					
						
							| 
									
										
										
										
											2021-06-21 22:53:04 +00:00
										 |  |  |                 votersFile.write(replyJson['actor'] + | 
					
						
							|  |  |  |                                  votersFileSeparator + | 
					
						
							|  |  |  |                                  foundAnswer + '\n') | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             # change an entry in the voters file | 
					
						
							| 
									
										
										
										
											2021-07-13 14:40:49 +00:00
										 |  |  |             with open(votersFilename, 'r') as votersFile: | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |                 lines = votersFile.readlines() | 
					
						
							|  |  |  |                 newlines = [] | 
					
						
							|  |  |  |                 saveVotersFile = False | 
					
						
							| 
									
										
										
										
											2019-11-29 19:22:11 +00:00
										 |  |  |                 for voteLine in lines: | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |                     if voteLine.startswith(replyJson['actor'] + | 
					
						
							|  |  |  |                                            votersFileSeparator): | 
					
						
							|  |  |  |                         newVoteLine = replyJson['actor'] + \ | 
					
						
							|  |  |  |                             votersFileSeparator + foundAnswer + '\n' | 
					
						
							|  |  |  |                         if voteLine == newVoteLine: | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |                             break | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |                         saveVotersFile = True | 
					
						
							| 
									
										
										
										
											2019-11-29 19:22:11 +00:00
										 |  |  |                         newlines.append(newVoteLine) | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         newlines.append(voteLine) | 
					
						
							|  |  |  |                 if saveVotersFile: | 
					
						
							| 
									
										
										
										
											2020-08-29 11:14:19 +00:00
										 |  |  |                     with open(votersFilename, 'w+') as votersFile: | 
					
						
							| 
									
										
										
										
											2019-11-29 19:22:11 +00:00
										 |  |  |                         for voteLine in newlines: | 
					
						
							|  |  |  |                             votersFile.write(voteLine) | 
					
						
							|  |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |                     return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     # update the vote counts | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |     questionTotalsChanged = False | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |     for possibleAnswer in questionJson['object']['oneOf']: | 
					
						
							|  |  |  |         if not possibleAnswer.get('name'): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |         totalItems = 0 | 
					
						
							| 
									
										
										
										
											2021-07-13 14:40:49 +00:00
										 |  |  |         with open(votersFilename, 'r') as votersFile: | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |             lines = votersFile.readlines() | 
					
						
							| 
									
										
										
										
											2019-11-29 18:46:21 +00:00
										 |  |  |             for voteLine in lines: | 
					
						
							| 
									
										
										
										
											2020-04-04 10:12:34 +00:00
										 |  |  |                 if voteLine.endswith(votersFileSeparator + | 
					
						
							|  |  |  |                                      possibleAnswer['name'] + '\n'): | 
					
						
							|  |  |  |                     totalItems += 1 | 
					
						
							|  |  |  |         if possibleAnswer['replies']['totalItems'] != totalItems: | 
					
						
							|  |  |  |             possibleAnswer['replies']['totalItems'] = totalItems | 
					
						
							|  |  |  |             questionTotalsChanged = True | 
					
						
							| 
									
										
										
										
											2019-11-29 19:22:11 +00:00
										 |  |  |     if not questionTotalsChanged: | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2019-11-29 19:22:11 +00:00
										 |  |  |     # save the question with altered totals | 
					
						
							| 
									
										
										
										
											2021-12-26 14:47:21 +00:00
										 |  |  |     save_json(questionJson, questionPostFilename) | 
					
						
							| 
									
										
										
										
											2021-11-03 21:53:30 +00:00
										 |  |  |     return questionJson, questionPostFilename | 
					
						
							| 
									
										
										
										
											2020-11-09 15:40:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def isQuestion(postObjectJson: {}) -> bool: | 
					
						
							|  |  |  |     """ is the given post a question?
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if postObjectJson['type'] != 'Create' and \ | 
					
						
							|  |  |  |        postObjectJson['type'] != 'Update': | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-26 10:57:03 +00:00
										 |  |  |     if not has_object_dict(postObjectJson): | 
					
						
							| 
									
										
										
										
											2020-11-09 15:40:24 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  |     if not postObjectJson['object'].get('type'): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if postObjectJson['object']['type'] != 'Question': | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if not postObjectJson['object'].get('oneOf'): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if not isinstance(postObjectJson['object']['oneOf'], list): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     return True |