Modern ActivityPub compliant server, designed for simplicity and accessibility. Includes calendar and sharing economy features to empower your federated community. https://code.freedombone.net/bashrc/epicyon Docs: https://epicyon.net/#install
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

question.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. __filename__ = "question.py"
  2. __author__ = "Bob Mottram"
  3. __license__ = "AGPL3+"
  4. __version__ = "1.2.0"
  5. __maintainer__ = "Bob Mottram"
  6. __email__ = "bob@freedombone.net"
  7. __status__ = "Production"
  8. import os
  9. from utils import locatePost
  10. from utils import loadJson
  11. from utils import saveJson
  12. def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
  13. replyJson: {}) -> {}:
  14. """ For a given reply update the votes on a question
  15. Returns the question json object if the vote totals were changed
  16. """
  17. if not replyJson.get('object'):
  18. return None
  19. if not isinstance(replyJson['object'], dict):
  20. return None
  21. if not replyJson['object'].get('inReplyTo'):
  22. return None
  23. if not replyJson['object']['inReplyTo']:
  24. return None
  25. if not isinstance(replyJson['object']['inReplyTo'], str):
  26. return None
  27. if not replyJson['object'].get('name'):
  28. return None
  29. inReplyTo = replyJson['object']['inReplyTo']
  30. questionPostFilename = locatePost(baseDir, nickname, domain, inReplyTo)
  31. if not questionPostFilename:
  32. return None
  33. questionJson = loadJson(questionPostFilename)
  34. if not questionJson:
  35. return None
  36. if not questionJson.get('object'):
  37. return None
  38. if not isinstance(questionJson['object'], dict):
  39. return None
  40. if not questionJson['object'].get('type'):
  41. return None
  42. if questionJson['type'] != 'Question':
  43. return None
  44. if not questionJson['object'].get('oneOf'):
  45. return None
  46. if not isinstance(questionJson['object']['oneOf'], list):
  47. return None
  48. if not questionJson['object'].get('content'):
  49. return None
  50. replyVote = replyJson['object']['name']
  51. # does the reply name field match any possible question option?
  52. foundAnswer = None
  53. for possibleAnswer in questionJson['object']['oneOf']:
  54. if not possibleAnswer.get('name'):
  55. continue
  56. if possibleAnswer['name'] == replyVote:
  57. foundAnswer = possibleAnswer
  58. break
  59. if not foundAnswer:
  60. return None
  61. # update the voters file
  62. votersFileSeparator = ';;;'
  63. votersFilename = questionPostFilename.replace('.json', '.voters')
  64. if not os.path.isfile(votersFilename):
  65. # create a new voters file
  66. votersFile = open(votersFilename, 'w+')
  67. if votersFile:
  68. votersFile.write(replyJson['actor'] +
  69. votersFileSeparator +
  70. foundAnswer + '\n')
  71. votersFile.close()
  72. else:
  73. if replyJson['actor'] not in open(votersFilename).read():
  74. # append to the voters file
  75. votersFile = open(votersFilename, "a+")
  76. if votersFile:
  77. votersFile.write(replyJson['actor'] +
  78. votersFileSeparator +
  79. foundAnswer + '\n')
  80. votersFile.close()
  81. else:
  82. # change an entry in the voters file
  83. with open(votersFilename, "r") as votersFile:
  84. lines = votersFile.readlines()
  85. newlines = []
  86. saveVotersFile = False
  87. for voteLine in lines:
  88. if voteLine.startswith(replyJson['actor'] +
  89. votersFileSeparator):
  90. newVoteLine = replyJson['actor'] + \
  91. votersFileSeparator + foundAnswer + '\n'
  92. if voteLine == newVoteLine:
  93. break
  94. saveVotersFile = True
  95. newlines.append(newVoteLine)
  96. else:
  97. newlines.append(voteLine)
  98. if saveVotersFile:
  99. with open(votersFilename, 'w+') as votersFile:
  100. for voteLine in newlines:
  101. votersFile.write(voteLine)
  102. else:
  103. return None
  104. # update the vote counts
  105. questionTotalsChanged = False
  106. for possibleAnswer in questionJson['object']['oneOf']:
  107. if not possibleAnswer.get('name'):
  108. continue
  109. totalItems = 0
  110. with open(votersFilename, "r") as votersFile:
  111. lines = votersFile.readlines()
  112. for voteLine in lines:
  113. if voteLine.endswith(votersFileSeparator +
  114. possibleAnswer['name'] + '\n'):
  115. totalItems += 1
  116. if possibleAnswer['replies']['totalItems'] != totalItems:
  117. possibleAnswer['replies']['totalItems'] = totalItems
  118. questionTotalsChanged = True
  119. if not questionTotalsChanged:
  120. return None
  121. # save the question with altered totals
  122. saveJson(questionJson, questionPostFilename)
  123. return questionJson
  124. def isQuestion(postObjectJson: {}) -> bool:
  125. """ is the given post a question?
  126. """
  127. if postObjectJson['type'] != 'Create' and \
  128. postObjectJson['type'] != 'Update':
  129. return False
  130. if not isinstance(postObjectJson['object'], dict):
  131. return False
  132. if not postObjectJson['object'].get('type'):
  133. return False
  134. if postObjectJson['object']['type'] != 'Question':
  135. return False
  136. if not postObjectJson['object'].get('oneOf'):
  137. return False
  138. if not isinstance(postObjectJson['object']['oneOf'], list):
  139. return False
  140. return True