Permalink
Browse files

Merge branch 'master' into jquerymobile

Conflicts:
	geocamTalk/templates/geocamTalk/base.html
	geocamTalk/templates/geocamTalk/message_list.html

Resolved conflicts application appears to be working except for a
QuickTime loading issue, need to explore if it's because of the merge or
because of jQuery Mobile
  • Loading branch information...
2 parents 543bae2 + 05c8d1f commit 221a2e3e0b8df5a97b33ac714096d80484050f06 @ahsteele ahsteele committed Apr 14, 2011
Showing with 921 additions and 349 deletions.
  1. +3 −1 .gitignore
  2. +58 −1 README.rst
  3. +1 −1 example/manage.py
  4. +1 −1 example/settings.py
  5. +5 −0 geocamMemo/authentication_example.py
  6. +16 −16 geocamMemo/fixtures/demoMemoMessages.json
  7. +24 −1 geocamMemo/models.py
  8. +31 −13 geocamMemo/templates/geocamMemo/message_form.html
  9. +25 −10 geocamMemo/tests/unit.py
  10. +11 −1 geocamMemo/tests/urls.py
  11. +23 −2 geocamMemo/tests/views.py
  12. +4 −2 geocamMemo/urls.py
  13. +25 −4 geocamMemo/views.py
  14. +2 −0 geocamTalk/admin.py
  15. +8 −8 geocamTalk/fixtures/demoTalkMessages.json
  16. +2 −1 geocamTalk/management/commands/randomtalk.py
  17. +152 −83 geocamTalk/models.py
  18. +4 −3 geocamTalk/templates/geocamTalk/base.html
  19. +9 −7 geocamTalk/templates/geocamTalk/message_list.html
  20. +16 −1 geocamTalk/tests/functional.py
  21. +177 −66 geocamTalk/tests/unit.py
  22. +25 −3 geocamTalk/tests/urls.py
  23. +123 −20 geocamTalk/tests/views.py
  24. +6 −0 geocamTalk/urls.py
  25. +170 −104 geocamTalk/views.py
  26. 0 revisions/__init__.py
  27. 0 revisions/admin.py
  28. 0 revisions/managers.py
  29. 0 revisions/middleware.py
  30. 0 revisions/models.py
  31. 0 revisions/shortcuts.py
  32. 0 revisions/tests/__init__.py
  33. 0 revisions/tests/admin.py
  34. 0 revisions/tests/fixtures/asides_scenario.json
  35. 0 revisions/tests/fixtures/fancy_revisions_scenario.json
  36. 0 revisions/tests/fixtures/revisions_scenario.json
  37. 0 revisions/tests/fixtures/trashable_scenario.json
  38. 0 revisions/tests/fixtures/users.json
  39. 0 revisions/tests/models.py
  40. 0 revisions/tests/tests.py
  41. 0 revisions/tests/urls.py
  42. 0 revisions/views.py
View
@@ -12,4 +12,6 @@ media/css/*.r*.css
.project
.pydevproject
.tmp*
-.settings
+.settings
+geocamMemo/authentication.py
+example/media/*
View
@@ -1,4 +1,61 @@
-Fill me in some time in the future with list view awesomeness
+===============
+GeoCam Memo Web
+===============
+
+.. sectnum::
+
+.. contents:: Contents
+
+About
+-----
+
+The GeoCam Project helps people better understand and respond to disasters.
+GeoCam consists of a GPS-enabled camera (or cell phone) and a web app for
+sharing geotagged photos and other geospatial data.
+
+GeoCam Memo is a scribing and note-taking application intended for use by search team members as they canvas the scene of a disaster. Notes can be recorded using text or audio and various forms of attachments (including but not limited to images) can be attached for transmission to a central server. All messages can be geotagged and categorized before saving to provide proper context when analyzing them via a web interface at a later time.
+
+GeoCam Talk is a communication application intended to aid in communication during a search mission. Members can send text and audio messages to any subset of their team members while on the field from their mobile devices. All messages are sent through a central server which catalogs them for later analysis. Just as in Memo, all messages are geotagged to provide instant awareness of team member location.
+
+This is the web application for both GeoCam Memo and GeoCam Talk
+
+News
+----
+
+Visit http://sites.google.com/site/geocampracticum2011/ and http://disastercam.blogspot.com/ for updates.
+
+Setup
+-----
+The GeoCam Memo and Talk applications were built using the Django framework and run on top of Python.
+
+Dependencies
+~~~~~~~~~~~~
+ * Python 2.4 or higher (http://www.python.org/download/)
+ * Django 1.2.5 or greater (http://www.djangoproject.com/)
+
+1. Once all dependencies have been installed, clone the GeoCamMemoWeb repository to the path of your choice::
+
+ git clone git@github.com:cheeseinvert/geocamMemoWeb.git
+
+2. CD into your ./geocamMemoWeb/example path and run syncdb, creating an admin user if prompted::
+
+ python manage.py syncdb
+
+Running
+-------
+To run a development server, navigate to your ./geocamMemoWeb/example path and execute runserver::
+
+ python manage.py runserver 0.0.0.0:8000
+
+Pleast note that this must be done before the geocamTalkForAndroid and geocamTalkForMemo can be successfully run on your mobile device.
+
+Testing
+-------
+Testing can be initiated from your ./geocamMemoWeb/example path using the test command::
+
+ python manage.py test geocamMemo geocamTalk
+
+See the Django documentation for more information on using manage.py
| __BEGIN_LICENSE__
| Copyright (C) 2008-2010 United States Government as represented by
View
2 example/manage.py 100755 → 100644
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python
# __BEGIN_LICENSE__
# Copyright (C) 2008-2010 United States Government as represented by
# the Administrator of the National Aeronautics and Space Administration.
View
@@ -31,7 +31,7 @@
# although not all choices may be available on all operating systems.
# If running in a Windows environment this must be set to the same as your
# system time zone.
-TIME_ZONE = 'America/Chicago'
+TIME_ZONE = 'UTC'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
@@ -0,0 +1,5 @@
+GOOGLE_TOKEN = "blahblahblah" #copy paste your token
+
+#SID=DQAAAK4AAABnT14QB__UrAs3MtBH-6jBOPl4jMtBEZNPvneo7wAClyUmgQCSm-_CIcjBGuQxRxWNKY1S4fC17lZbGhObYVmHPT9LnHXCiqwX8WSr2mK-sFSt0k9HSVBeelAlgEWmttPcatEVOJc_Y5v_7Kj9vg4vIPA2CY6UdJkbMW0w2F5r-xSbVH5v5UUw-wnKb-PSPhLIru9DRJIqbBQ_yz4DB6d3vJ7Z-VNrhibGm49XGoV85Q
+#LSID=DQAAALAAAACeW15pZqyexp0R9ir_Cuq5dLWKCumwmhHZVcMrcTgGvAhsD8eMl237RJNcvo5nMOCjD388sRH_Vj1x7osIFT1DFAjeppjqGWu9Wq8hQJv0yz-fvHiJMk_vJDst6NyFGItSO6hiQEv-IXCjB8OUxuY2UdLSTyMrLuyoTf_7G5r4MlYDdd5pxz5iwRdkvZrm3zqOV4ugdAWaZLDRoqLznClgYUDEJhEbP8WYuHSeeu70wg
+#Auth=DQAAALEAAABPA8N3cKFKcS-tke29PQRlOMBop3IcJvi6MVs6B81GFlG1Tf4PEAM7r0vbDABijydybEzXPx-4a6DE8BDzQVrkw5AgEvaerPQeIlGuW0mY_y8l6Bb3w04MPDSH_rcMugG6ogZr2EebL0VB0W8dGOSoxnOyqKlwUHD2j8NaLGsJEresYajYRnorDTcKS1mwhrXkjXIjZAjqg155hFFMTCC6kPL05itxdKu0kbrJ2lmNBiNs4xoqJKrEow5NksKioiA
@@ -1,65 +1,65 @@
[
{"pk": 2, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.06008, "heading": null, "content": "CMUSV building inspection completed,structure is sound. Search commencing shortly.", "content_timestamp": "2011-03-13 10:32:40", "position_timestamp": "2011-03-13 10:32:35", "latitude": 37.410433, "speed": null, "cid": "7dcfed1377864954875731ef5e78b5eb", "accuracy": 80.0}
+{"author": 2, "altitude": null, "longitude": -122.06008, "heading": null, "content": "CMUSV building inspection completed,structure is sound. Search commencing shortly.", "content_timestamp": "2011-03-13 10:32:40", "server_timestamp": "2011-03-13 10:32:40", "position_timestamp": "2011-03-13 10:32:35", "latitude": 37.410433, "speed": null, "cid": "7dcfed1377864954875731ef5e78b5eb", "accuracy": 80.0}
}
,
{"pk": 3, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.059811, "heading": null, "content": "Entering CMUSV building. Minimal damage. Victims visible and in good conditions / spirits.", "content_timestamp": "2011-03-13 10:33:43", "position_timestamp": "2011-03-13 10:33:41", "latitude": 37.410565, "speed": null, "cid": "accb13e490be4aa48a352a4028034afb", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.059811, "heading": null, "content": "Entering CMUSV building. Minimal damage. Victims visible and in good conditions / spirits.", "content_timestamp": "2011-03-13 10:33:43", "server_timestamp": "2011-03-13 10:33:43", "position_timestamp": "2011-03-13 10:33:41", "latitude": 37.410565, "speed": null, "cid": "accb13e490be4aa48a352a4028034afb", "accuracy": 60.0}
}
,
{"pk": 4, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.059735, "heading": null, "content": "2 people found inCMUSV building and safely removed.", "content_timestamp": "2011-03-13 10:35:34", "position_timestamp": "2011-03-13 10:35:31", "latitude": 37.41049, "speed": null, "cid": "c527b009a4694b78afe21b6c5f068d06", "accuracy": 250.0}
+{"author": 2, "altitude": null, "longitude": -122.059735, "heading": null, "content": "2 people found inCMUSV building and safely removed.", "content_timestamp": "2011-03-13 10:35:34", "server_timestamp": "2011-03-13 10:35:34", "position_timestamp": "2011-03-13 10:35:31", "latitude": 37.41049, "speed": null, "cid": "c527b009a4694b78afe21b6c5f068d06", "accuracy": 250.0}
}
,
{"pk": 5, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.059913, "heading": null, "content": "Exiting CMUSV building. Total of 2 people found.", "content_timestamp": "2011-03-13 10:37:04", "position_timestamp": "2011-03-13 10:36:59", "latitude": 37.4103, "speed": null, "cid": "89a9fb8eb7c74d53be7fd8aa799727b0", "accuracy": 100.0}
+{"author": 2, "altitude": null, "longitude": -122.059913, "heading": null, "content": "Exiting CMUSV building. Total of 2 people found.", "content_timestamp": "2011-03-13 10:37:04", "server_timestamp": "2011-03-13 10:37:04", "position_timestamp": "2011-03-13 10:36:59", "latitude": 37.4103, "speed": null, "cid": "89a9fb8eb7c74d53be7fd8aa799727b0", "accuracy": 100.0}
}
,
{"pk": 6, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.059455, "heading": null, "content": "Victim hiding behind bushes.Not physically injured. Directed to basecamp.", "content_timestamp": "2011-03-13 10:37:33", "position_timestamp": "2011-03-13 10:37:29", "latitude": 37.410373, "speed": null, "cid": "359d2470736a4d998ff9150d0d8ece88", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.059455, "heading": null, "content": "Victim hiding behind bushes.Not physically injured. Directed to basecamp.", "content_timestamp": "2011-03-13 10:37:33", "server_timestamp": "2011-03-13 10:37:33", "position_timestamp": "2011-03-13 10:37:29", "latitude": 37.410373, "speed": null, "cid": "359d2470736a4d998ff9150d0d8ece88", "accuracy": 60.0}
}
,
{"pk": 7, "model": "geocamMemo.memomessage", "fields":
-{"author": 3, "altitude": null, "longitude": -122.060458, "heading": null, "content": "Victim approaching basecamp from north-eastcorner of CMUSV building.", "content_timestamp": "2011-03-13 10:39:17", "position_timestamp": "2011-03-13 10:39:15", "latitude": 37.409502, "speed": null, "cid": "bdd444d39d8d42e9ad0e4ba5b6e443f3", "accuracy": 60.0}
+{"author": 3, "altitude": null, "longitude": -122.060458, "heading": null, "content": "Victim approaching basecamp from north-eastcorner of CMUSV building.", "content_timestamp": "2011-03-13 10:39:17", "server_timestamp": "2011-03-13 10:39:17", "position_timestamp": "2011-03-13 10:39:15", "latitude": 37.409502, "speed": null, "cid": "bdd444d39d8d42e9ad0e4ba5b6e443f3", "accuracy": 60.0}
}
,
{"pk": 8, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.059465, "heading": null, "content": "CMUSV campus cleared. Moving on to next structure.", "content_timestamp": "2011-03-13 10:40:49", "position_timestamp": "2011-03-13 10:40:44", "latitude": 37.409975, "speed": null, "cid": "de22bfcf740b405298df5d15fece6c3f", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.059465, "heading": null, "content": "CMUSV campus cleared. Moving on to next structure.", "content_timestamp": "2011-03-13 10:40:49", "server_timestamp": "2011-03-13 10:40:49", "position_timestamp": "2011-03-13 10:40:44", "latitude": 37.409975, "speed": null, "cid": "de22bfcf740b405298df5d15fece6c3f", "accuracy": 60.0}
}
,
{"pk": 9, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.058602, "heading": null, "content": "Arrived at 2nd structure. Integrity of building in question. Southwest corner has collapsed. Structural engineer assessment in progress.", "content_timestamp": "2011-03-13 10:41:31", "position_timestamp": "2011-03-13 10:41:28", "latitude": 37.410379, "speed": null, "cid": "d3d6e7a010494b578cacb8d9c414f6e8", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.058602, "heading": null, "content": "Arrived at 2nd structure. Integrity of building in question. Southwest corner has collapsed. Structural engineer assessment in progress.", "content_timestamp": "2011-03-13 10:41:31", "server_timestamp": "2011-03-13 10:41:31", "position_timestamp": "2011-03-13 10:41:28", "latitude": 37.410379, "speed": null, "cid": "d3d6e7a010494b578cacb8d9c414f6e8", "accuracy": 60.0}
}
,
{"pk": 10, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.058384, "heading": null, "content": "Structural assessment complete. Building is too dangerous to complete full search. Proceeding through north-east half of structure.", "content_timestamp": "2011-03-13 10:44:16", "position_timestamp": "2011-03-13 10:43:04", "latitude": 37.410737, "speed": null, "cid": "66de91e469df4543a91cf1732e22627a", "accuracy": 90.0}
+{"author": 2, "altitude": null, "longitude": -122.058384, "heading": null, "content": "Structural assessment complete. Building is too dangerous to complete full search. Proceeding through north-east half of structure.", "content_timestamp": "2011-03-13 10:44:16", "server_timestamp": "2011-03-13 10:44:16", "position_timestamp": "2011-03-13 10:43:04", "latitude": 37.410737, "speed": null, "cid": "66de91e469df4543a91cf1732e22627a", "accuracy": 90.0}
}
,
{"pk": 11, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.0584, "heading": null, "content": "Structure search complete. No victims found.", "content_timestamp": "2011-03-13 10:45:15", "position_timestamp": "2011-03-13 10:44:59", "latitude": 37.410532, "speed": null, "cid": "20a0d558c9ea4d2ba372310200ffe641", "accuracy": 150.0}
+{"author": 2, "altitude": null, "longitude": -122.0584, "heading": null, "content": "Structure search complete. No victims found.", "content_timestamp": "2011-03-13 10:45:15", "server_timestamp": "2011-03-13 10:45:15", "position_timestamp": "2011-03-13 10:44:59", "latitude": 37.410532, "speed": null, "cid": "20a0d558c9ea4d2ba372310200ffe641", "accuracy": 150.0}
}
,
{"pk": 14, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.057961, "heading": null, "content": "Blazing fire visible in building to immediate north.", "content_timestamp": "2011-03-13 10:48:12", "position_timestamp": "2011-03-13 10:48:11", "latitude": 37.411098, "speed": null, "cid": "5da27492966f47d087cc5a0bf851e8c7", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.057961, "heading": null, "content": "Blazing fire visible in building to immediate north.", "content_timestamp": "2011-03-13 10:48:12", "server_timestamp": "2011-03-13 10:48:12", "position_timestamp": "2011-03-13 10:48:11", "latitude": 37.411098, "speed": null, "cid": "5da27492966f47d087cc5a0bf851e8c7", "accuracy": 60.0}
}
,
{"pk": 15, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.057954, "heading": null, "content": "Structural engineer not allowing access to building. Fire is too out of control. Fire squad alerted.", "content_timestamp": "2011-03-13 10:48:44", "position_timestamp": "2011-03-13 10:48:45", "latitude": 37.411629, "speed": null, "cid": "75152aefde2c47a489083007a848c1e2", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.057954, "heading": null, "content": "Structural engineer not allowing access to building. Fire is too out of control. Fire squad alerted.", "content_timestamp": "2011-03-13 10:48:44", "server_timestamp": "2011-03-13 10:48:44", "position_timestamp": "2011-03-13 10:48:45", "latitude": 37.411629, "speed": null, "cid": "75152aefde2c47a489083007a848c1e2", "accuracy": 60.0}
}
,
{"pk": 16, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.057987, "heading": null, "content": "Five people found hiding in empty pool. Directed back to base camp.", "content_timestamp": "2011-03-13 10:46:20", "position_timestamp": "2011-03-13 10:46:18", "latitude": 37.410376, "speed": null, "cid": "1d58e95413354379a112a63fc5683500", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.057987, "heading": null, "content": "Five people found hiding in empty pool. Directed back to base camp.", "content_timestamp": "2011-03-13 10:46:20", "server_timestamp": "2011-03-13 10:46:20", "position_timestamp": "2011-03-13 10:46:18", "latitude": 37.410376, "speed": null, "cid": "1d58e95413354379a112a63fc5683500", "accuracy": 60.0}
}
,
{"pk": 17, "model": "geocamMemo.memomessage", "fields":
-{"author": 3, "altitude": null, "longitude": -122.0603532, "heading": null, "content": "Five victims arrived at base camp.", "content_timestamp": "2011-03-13 10:47:26", "position_timestamp": "2011-03-13 10:47:25", "latitude": 37.4093296, "speed": null, "cid": "b7fab28925c145d996ecda1d539d0ec9", "accuracy": 60.0}
+{"author": 3, "altitude": null, "longitude": -122.0603532, "heading": null, "content": "Five victims arrived at base camp.", "content_timestamp": "2011-03-13 10:47:26", "server_timestamp": "2011-03-13 10:47:26", "position_timestamp": "2011-03-13 10:47:25", "latitude": 37.4093296, "speed": null, "cid": "b7fab28925c145d996ecda1d539d0ec9", "accuracy": 60.0}
}
,
{"pk": 18, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": -122.060353, "heading": null, "content": "Initializing search from base camp. Clear skies should allow for thorough search today. Smoke, potentially fire, visible in the distance.", "content_timestamp": "2011-03-13 10:27:45", "position_timestamp": "2011-03-13 10:27:42", "latitude": 37.409409, "speed": null, "cid": "bfeaaeecd86f44c8ab1acb510dc4c7dc", "accuracy": 60.0}
+{"author": 2, "altitude": null, "longitude": -122.060353, "heading": null, "content": "Initializing search from base camp. Clear skies should allow for thorough search today. Smoke, potentially fire, visible in the distance.", "content_timestamp": "2011-03-13 10:27:45", "server_timestamp": "2011-03-13 10:27:45", "position_timestamp": "2011-03-13 10:27:42", "latitude": 37.409409, "speed": null, "cid": "bfeaaeecd86f44c8ab1acb510dc4c7dc", "accuracy": 60.0}
}
,
{"pk": 19, "model": "geocamMemo.memomessage", "fields":
-{"author": 2, "altitude": null, "longitude": null, "heading": null, "content": "Crap, my geolocation service crashed and I am not providing geoloc with this message. This message should be the latest to make sure we gracefully fall back to the next available geolocated message.", "content_timestamp": "2011-03-13 11:23:21", "position_timestamp": null, "latitude": null, "speed": null, "cid": "e1945c241bde4238ac0c2869812a97be", "accuracy": null}
+{"author": 2, "altitude": null, "longitude": null, "heading": null, "content": "Crap, my geolocation service crashed and I am not providing geoloc with this message. This message should be the latest to make sure we gracefully fall back to the next available geolocated message.", "content_timestamp": "2011-03-13 11:23:21", "server_timestamp": "2011-03-13 11:23:21", "position_timestamp": null, "latitude": null, "speed": null, "cid": "e1945c241bde4238ac0c2869812a97be", "accuracy": null}
}
]
View
@@ -10,6 +10,8 @@
from revisions.shortcuts import VersionedModel as VersionedModelShortcuts
import revisions
import json
+import time, datetime
+from geocamMemo import authentication
class GeocamMessage(revisions.models.VersionedModel):
""" This is the abstract data model for geocam messages
@@ -29,6 +31,7 @@ class GeocamMessage(revisions.models.VersionedModel):
class Meta:
abstract = True
+ server_timestamp = models.DateTimeField(auto_now_add = True)
author = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_set")
content = models.TextField(max_length=1024)
# removed auto_add_now from content_timestamp since revisions are also instances in the
@@ -45,6 +48,9 @@ class Meta:
def get_date_string(self):
return self.content_timestamp.strftime("%m/%d/%y %H:%M:%S")
+ def get_date_timestamp(self):
+ return int(time.mktime(self.content_timestamp.timetuple())) * 1000 # * 1000 for java timestamp
+
def get_author_string(self):
return get_user_string(self.author)
@@ -80,11 +86,28 @@ def getJson(self):
authorUsername=self.author.username,
authorFullname=self.get_author_string(),
content=self.content,
- contentTimestamp=self.get_date_string(),
+ contentTimestamp=self.get_date_timestamp(),
latitude=self.latitude,
longitude=self.longitude,
accuracy=self.accuracy,
hasGeolocation=bool(self.has_geolocation()) )
+
+ @staticmethod
+ def fromJson(messageDict):
+ message = MemoMessage()
+ if "content" in messageDict:
+ message.content = messageDict["content"]
+ if "contentTimestamp" in messageDict:
+ message.content_timestamp = datetime.datetime.fromtimestamp(float(messageDict["contentTimestamp"]) / 1000)
+ if "latitude" in messageDict:
+ message.latitude = messageDict["latitude"]
+ if "longitude" in messageDict:
+ message.longitude = messageDict["longitude"]
+ if "accuracy" in messageDict:
+ message.accuracy = messageDict["accuracy"]
+ if "userId" in messageDict:
+ message.author_id = messageDict["userId"]
+ return message
@staticmethod
def getMessages(author=None):
Oops, something went wrong.

0 comments on commit 221a2e3

Please sign in to comment.