in api/pages/mail/mood.py [0:0]
def run(API, environ, indata, session):
# We need to be logged in for this!
if not session.user:
raise API.exception(403, "You must be logged in to use this API endpoint! %s")
# First, fetch the view if we have such a thing enabled
viewList = []
if indata.get('view'):
viewList = session.getView(indata.get('view'))
if indata.get('subfilter'):
viewList = session.subFilter(indata.get('subfilter'), view = viewList)
dateTo = indata.get('to', int(time.time()))
dateFrom = indata.get('from', dateTo - (86400*30*6)) # Default to a 6 month span
# Define moods we know of
moods_good = set(['trust', 'joy', 'confident', 'positive'])
moods_bad = set(['sadness', 'anger', 'disgust', 'fear', 'negative'])
moods_neutral = set(['anticipation', 'surprise', 'tentative', 'analytical', 'neutral'])
all_moods = set(moods_good | moods_bad | moods_neutral)
# Start off with a query for the entire org (we want to compare)
dOrg = session.user['defaultOrganisation'] or "apache"
query = {
'query': {
'bool': {
'must': [
{'range':
{
'ts': {
'from': dateFrom,
'to': dateTo
}
}
},
{
'term': {
'organisation': dOrg
}
},
{ 'exists': {
'field': 'mood'
}
}
]
}
}
}
# Count all emails, for averaging scores
gemls = session.DB.ES.count(
index=session.DB.dbname,
doc_type="email",
body = query
)['count']
# Add aggregations for moods
query['aggs'] = {
}
for mood in all_moods:
query['aggs'][mood] = {
'sum': {
'field': "mood.%s" % mood
}
}
global_mood_compiled = {}
mood_compiled = {}
txt = "This chart shows the ten potential mood types as they average on the emails in this period. A score of 100 means a sentiment is highly visible in most emails."
gtxt = "This shows the overall estimated mood as a gauge from terrible to good."
# If we're comparing against all lists, first do a global query
# and compile moods overall
if indata.get('relative'):
txt = "This chart shows the ten potential mood types on the selected lists as they compare against all mailing lists in the database. A score of 100 here means the sentiment conforms to averages across all lists."
gtxt = "This shows the overall estimated mood compared to all lists, as a gauge from terrible to good."
global_moods = {}
gres = session.DB.ES.search(
index=session.DB.dbname,
doc_type="email",
size = 0,
body = query
)
for mood, el in gres['aggregations'].items():
# If a mood is not present (iow sum is 0), remove it from the equation by setting to -1
if el['value'] == 0:
el['value'] == -1
global_moods[mood] = el['value']
for k, v in global_moods.items():
if v >= 0:
global_mood_compiled[k] = int( (v / max(1,gemls)) * 100)
# Now, if we have a view (or not distinguishing), ...
ss = False
if indata.get('source'):
query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}})
ss = True
elif viewList:
query['query']['bool']['must'].append({'terms': {'sourceID': viewList}})
ss = True
# If we have a view enabled (and distinguish), compile local view against global view
# Else, just copy global as local
if ss or not indata.get('relative'):
res = session.DB.ES.search(
index=session.DB.dbname,
doc_type="email",
size = 0,
body = query
)
del query['aggs'] # we have to remove these to do a count()
emls = session.DB.ES.count(
index=session.DB.dbname,
doc_type="email",
body = query
)['count']
moods = {}
years = 0
for mood, el in res['aggregations'].items():
if el['value'] == 0:
el['value'] == -1
moods[mood] = el['value']
for k, v in moods.items():
if v > 0:
mood_compiled[k] = int(100 * int( ( v / max(1,emls)) * 100) / max(1, global_mood_compiled.get(k, 100)))
else:
mood_compiled = global_mood_compiled
# If relative mode and a field is missing, assume 100 (norm)
if indata.get('relative'):
for M in all_moods:
if mood_compiled.get(M, 0) == 0:
mood_compiled[M] = 100
# Compile an overall happiness level
MAX = max(max(mood_compiled.values()),1)
X = 100 if indata.get('relative') else 0
bads = X
for B in moods_bad:
if mood_compiled.get(B) and mood_compiled[B] > X:
bads += mood_compiled[B]
happ = 50
goods = X
for B in moods_good:
if mood_compiled.get(B) and mood_compiled[B] > X:
goods += mood_compiled[B]
MAX = max(MAX, bads, goods)
if bads > 0:
happ -= (50*bads/MAX)
if goods > 0:
happ += (50*goods/MAX)
swingometer = max(0, min(100, happ))
# JSON out!
JSON_OUT = {
'relativeMode': True,
'text': txt,
'counts': mood_compiled,
'okay': True,
'gauge': {
'key': 'Happiness',
'value': swingometer,
'text': gtxt
}
}
yield json.dumps(JSON_OUT)