2020-02-22 19:11:51 +00:00
|
|
|
__filename__ = "happening.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
|
|
|
__version__ = "1.1.0"
|
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
__email__ = "bob@freedombone.net"
|
|
|
|
__status__ = "Production"
|
|
|
|
|
|
|
|
import json
|
|
|
|
import time
|
|
|
|
import os
|
|
|
|
from datetime import datetime
|
|
|
|
|
2020-02-22 19:13:55 +00:00
|
|
|
from utils import loadJson
|
|
|
|
from utils import locatePost
|
2020-02-22 19:11:51 +00:00
|
|
|
from utils import daysInMonth
|
|
|
|
from utils import mergeDicts
|
|
|
|
|
2020-02-24 11:10:48 +00:00
|
|
|
def isHappeningEvent(tag: {}) -> bool:
|
|
|
|
"""Is this tag an Event or Place ActivityStreams type?
|
|
|
|
"""
|
|
|
|
if not tag.get('type'):
|
|
|
|
return False
|
|
|
|
if tag['type']!='Event' and tag['type']!='Place':
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
def isHappeningPost(postJsonObject: {}) -> bool:
|
|
|
|
"""Is this a post with tags?
|
|
|
|
"""
|
|
|
|
if not postJsonObject:
|
|
|
|
return False
|
|
|
|
if not postJsonObject.get('object'):
|
|
|
|
return False
|
|
|
|
if not isinstance(postJsonObject['object'], dict):
|
|
|
|
return False
|
|
|
|
if not postJsonObject['object'].get('tag'):
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
2020-02-22 19:11:51 +00:00
|
|
|
def getTodaysEvents(baseDir: str,nickname: str,domain: str, \
|
2020-02-24 10:55:49 +00:00
|
|
|
currYear=None,currMonthNumber=None, \
|
|
|
|
currDayOfMonth=None) -> {}:
|
2020-02-22 19:11:51 +00:00
|
|
|
"""Retrieves calendar events for today
|
|
|
|
Returns a dictionary of lists containing Event and Place activities
|
|
|
|
"""
|
|
|
|
now=datetime.now()
|
|
|
|
if not currYear:
|
|
|
|
year=now.year
|
|
|
|
else:
|
|
|
|
year=currYear
|
|
|
|
if not currMonthNumber:
|
|
|
|
monthNumber=now.month
|
|
|
|
else:
|
|
|
|
monthNumber=currMonthNumber
|
|
|
|
if not currDayOfMonth:
|
|
|
|
dayNumber=now.day
|
|
|
|
else:
|
|
|
|
dayNumber=currDayOfMonth
|
2020-02-23 09:45:04 +00:00
|
|
|
|
|
|
|
calendarFilename= \
|
|
|
|
baseDir+'/accounts/'+nickname+'@'+domain+ \
|
|
|
|
'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt'
|
2020-02-22 19:11:51 +00:00
|
|
|
events={}
|
|
|
|
if not os.path.isfile(calendarFilename):
|
|
|
|
return events
|
2020-02-23 09:45:04 +00:00
|
|
|
|
2020-02-22 19:11:51 +00:00
|
|
|
calendarPostIds=[]
|
|
|
|
recreateEventsFile=False
|
|
|
|
with open(calendarFilename,'r') as eventsFile:
|
|
|
|
for postId in eventsFile:
|
|
|
|
postId=postId.replace('\n','')
|
|
|
|
postFilename=locatePost(baseDir,nickname,domain,postId)
|
|
|
|
if not postFilename:
|
|
|
|
recreateEventsFile=True
|
2020-02-23 09:49:10 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
postJsonObject=loadJson(postFilename)
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningPost(postJsonObject):
|
2020-02-23 09:49:10 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
postEvent=[]
|
|
|
|
dayOfMonth=None
|
|
|
|
for tag in postJsonObject['object']['tag']:
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningEvent(tag):
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# this tag is an event or a place
|
2020-02-23 09:49:10 +00:00
|
|
|
if tag['type']=='Event':
|
|
|
|
# tag is an event
|
|
|
|
if not tag.get('startTime'):
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-23 09:49:10 +00:00
|
|
|
eventTime= \
|
|
|
|
datetime.strptime(tag['startTime'], \
|
|
|
|
"%Y-%m-%dT%H:%M:%S%z")
|
|
|
|
if int(eventTime.strftime("%Y"))==year and \
|
|
|
|
int(eventTime.strftime("%m"))==monthNumber and \
|
|
|
|
int(eventTime.strftime("%d"))==dayNumber:
|
|
|
|
dayOfMonth=str(int(eventTime.strftime("%d")))
|
2020-02-23 11:25:16 +00:00
|
|
|
if '#statuses#' in postId:
|
2020-02-24 10:55:49 +00:00
|
|
|
# link to the id so that the event can be
|
|
|
|
# easily deleted
|
2020-02-23 11:25:16 +00:00
|
|
|
tag['postId']=postId.split('#statuses#')[1]
|
2020-02-22 19:11:51 +00:00
|
|
|
postEvent.append(tag)
|
2020-02-23 09:49:10 +00:00
|
|
|
else:
|
|
|
|
# tag is a place
|
|
|
|
postEvent.append(tag)
|
|
|
|
if postEvent and dayOfMonth:
|
|
|
|
calendarPostIds.append(postId)
|
|
|
|
if not events.get(dayOfMonth):
|
|
|
|
events[dayOfMonth]=[]
|
|
|
|
events[dayOfMonth].append(postEvent)
|
2020-02-22 19:11:51 +00:00
|
|
|
|
|
|
|
# if some posts have been deleted then regenerate the calendar file
|
|
|
|
if recreateEventsFile:
|
|
|
|
calendarFile=open(calendarFilename, "w")
|
|
|
|
for postId in calendarPostIds:
|
|
|
|
calendarFile.write(postId+'\n')
|
|
|
|
calendarFile.close()
|
|
|
|
|
|
|
|
return events
|
|
|
|
|
|
|
|
def todaysEventsCheck(baseDir: str,nickname: str,domain: str) -> bool:
|
|
|
|
"""Are there calendar events today?
|
|
|
|
"""
|
|
|
|
now=datetime.now()
|
|
|
|
year=now.year
|
|
|
|
monthNumber=now.month
|
|
|
|
dayNumber=now.day
|
|
|
|
|
2020-02-23 09:45:04 +00:00
|
|
|
calendarFilename= \
|
|
|
|
baseDir+'/accounts/'+nickname+'@'+domain+ \
|
|
|
|
'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt'
|
2020-02-22 19:11:51 +00:00
|
|
|
if not os.path.isfile(calendarFilename):
|
|
|
|
return False
|
2020-02-23 09:45:04 +00:00
|
|
|
|
2020-02-22 19:11:51 +00:00
|
|
|
eventsExist=False
|
|
|
|
with open(calendarFilename,'r') as eventsFile:
|
|
|
|
for postId in eventsFile:
|
|
|
|
postId=postId.replace('\n','')
|
|
|
|
postFilename=locatePost(baseDir,nickname,domain,postId)
|
2020-02-23 09:49:10 +00:00
|
|
|
if not postFilename:
|
|
|
|
continue
|
|
|
|
|
|
|
|
postJsonObject=loadJson(postFilename)
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningPost(postJsonObject):
|
2020-02-23 09:49:10 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
for tag in postJsonObject['object']['tag']:
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningEvent(tag):
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# this tag is an event or a place
|
|
|
|
if tag['type']!='Event':
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# tag is an event
|
|
|
|
if not tag.get('startTime'):
|
|
|
|
continue
|
|
|
|
eventTime= \
|
|
|
|
datetime.strptime(tag['startTime'], \
|
|
|
|
"%Y-%m-%dT%H:%M:%S%z")
|
|
|
|
if int(eventTime.strftime("%Y"))==year and \
|
|
|
|
int(eventTime.strftime("%m"))==monthNumber and \
|
|
|
|
int(eventTime.strftime("%d"))==dayNumber:
|
|
|
|
eventsExist=True
|
|
|
|
break
|
2020-02-22 19:11:51 +00:00
|
|
|
|
|
|
|
return eventsExist
|
|
|
|
|
|
|
|
def thisWeeksEventsCheck(baseDir: str,nickname: str,domain: str) -> bool:
|
|
|
|
"""Are there calendar events this week?
|
|
|
|
"""
|
|
|
|
now=datetime.now()
|
|
|
|
year=now.year
|
|
|
|
monthNumber=now.month
|
|
|
|
dayNumber=now.day
|
|
|
|
|
2020-02-23 09:45:04 +00:00
|
|
|
calendarFilename= \
|
|
|
|
baseDir+'/accounts/'+nickname+'@'+domain+ \
|
|
|
|
'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt'
|
2020-02-22 19:11:51 +00:00
|
|
|
if not os.path.isfile(calendarFilename):
|
|
|
|
return False
|
2020-02-23 09:45:04 +00:00
|
|
|
|
2020-02-22 19:11:51 +00:00
|
|
|
eventsExist=False
|
|
|
|
with open(calendarFilename,'r') as eventsFile:
|
|
|
|
for postId in eventsFile:
|
|
|
|
postId=postId.replace('\n','')
|
|
|
|
postFilename=locatePost(baseDir,nickname,domain,postId)
|
2020-02-23 09:49:10 +00:00
|
|
|
if not postFilename:
|
|
|
|
continue
|
|
|
|
|
|
|
|
postJsonObject=loadJson(postFilename)
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningPost(postJsonObject):
|
2020-02-23 09:49:10 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
for tag in postJsonObject['object']['tag']:
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningEvent(tag):
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# this tag is an event or a place
|
|
|
|
if tag['type']!='Event':
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# tag is an event
|
|
|
|
if not tag.get('startTime'):
|
|
|
|
continue
|
|
|
|
eventTime= \
|
|
|
|
datetime.strptime(tag['startTime'], \
|
|
|
|
"%Y-%m-%dT%H:%M:%S%z")
|
|
|
|
if int(eventTime.strftime("%Y"))==year and \
|
|
|
|
int(eventTime.strftime("%m"))==monthNumber and \
|
|
|
|
(int(eventTime.strftime("%d"))>dayNumber and \
|
|
|
|
int(eventTime.strftime("%d"))<=dayNumber+6):
|
|
|
|
eventsExist=True
|
|
|
|
break
|
2020-02-22 19:11:51 +00:00
|
|
|
|
|
|
|
return eventsExist
|
|
|
|
|
|
|
|
def getThisWeeksEvents(baseDir: str,nickname: str,domain: str) -> {}:
|
|
|
|
"""Retrieves calendar events for this week
|
2020-02-24 10:55:49 +00:00
|
|
|
Returns a dictionary indexed by day number of lists containing
|
|
|
|
Event and Place activities
|
2020-02-23 09:42:09 +00:00
|
|
|
Note: currently not used but could be with a weekly calendar screen
|
2020-02-22 19:11:51 +00:00
|
|
|
"""
|
|
|
|
now=datetime.now()
|
|
|
|
year=now.year
|
|
|
|
monthNumber=now.month
|
|
|
|
dayNumber=now.day
|
2020-02-23 09:45:04 +00:00
|
|
|
|
|
|
|
calendarFilename= \
|
|
|
|
baseDir+'/accounts/'+nickname+'@'+domain+ \
|
|
|
|
'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt'
|
|
|
|
|
2020-02-22 19:11:51 +00:00
|
|
|
events={}
|
|
|
|
if not os.path.isfile(calendarFilename):
|
|
|
|
return events
|
2020-02-23 09:45:04 +00:00
|
|
|
|
2020-02-22 19:11:51 +00:00
|
|
|
calendarPostIds=[]
|
|
|
|
recreateEventsFile=False
|
|
|
|
with open(calendarFilename,'r') as eventsFile:
|
|
|
|
for postId in eventsFile:
|
|
|
|
postId=postId.replace('\n','')
|
|
|
|
postFilename=locatePost(baseDir,nickname,domain,postId)
|
|
|
|
if not postFilename:
|
|
|
|
recreateEventsFile=True
|
2020-02-23 09:49:10 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
postJsonObject=loadJson(postFilename)
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningPost(postJsonObject):
|
2020-02-23 09:49:10 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
postEvent=[]
|
|
|
|
dayOfMonth=None
|
|
|
|
weekDayIndex=None
|
|
|
|
for tag in postJsonObject['object']['tag']:
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningEvent(tag):
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# this tag is an event or a place
|
2020-02-23 09:49:10 +00:00
|
|
|
if tag['type']=='Event':
|
|
|
|
# tag is an event
|
|
|
|
if not tag.get('startTime'):
|
2020-02-22 19:11:51 +00:00
|
|
|
continue
|
2020-02-23 09:49:10 +00:00
|
|
|
eventTime= \
|
|
|
|
datetime.strptime(tag['startTime'], \
|
|
|
|
"%Y-%m-%dT%H:%M:%S%z")
|
|
|
|
if int(eventTime.strftime("%Y"))==year and \
|
|
|
|
int(eventTime.strftime("%m"))==monthNumber and \
|
|
|
|
(int(eventTime.strftime("%d"))>=dayNumber and \
|
|
|
|
int(eventTime.strftime("%d"))<=dayNumber+6):
|
|
|
|
dayOfMonth=str(int(eventTime.strftime("%d")))
|
|
|
|
weekDayIndex=dayOfMonth-dayNumber
|
2020-02-22 19:11:51 +00:00
|
|
|
postEvent.append(tag)
|
2020-02-23 09:49:10 +00:00
|
|
|
else:
|
|
|
|
# tag is a place
|
|
|
|
postEvent.append(tag)
|
|
|
|
if postEvent and weekDayIndex:
|
|
|
|
calendarPostIds.append(postId)
|
|
|
|
if not events.get(dayOfMonth):
|
|
|
|
events[weekDayIndex]=[]
|
|
|
|
events[dayOfMonth].append(postEvent)
|
2020-02-22 19:11:51 +00:00
|
|
|
|
|
|
|
# if some posts have been deleted then regenerate the calendar file
|
|
|
|
if recreateEventsFile:
|
|
|
|
calendarFile=open(calendarFilename, "w")
|
|
|
|
for postId in calendarPostIds:
|
|
|
|
calendarFile.write(postId+'\n')
|
|
|
|
calendarFile.close()
|
|
|
|
|
|
|
|
lastDayOfMonth=daysInMonth(year,monthNumber)
|
|
|
|
if dayNumber+6 > lastDayOfMonth:
|
|
|
|
monthNumber+=1
|
|
|
|
if monthNumber>12:
|
|
|
|
monthNumber=1
|
|
|
|
year+=1
|
|
|
|
for d in range(1,dayNumber+6-lastDayOfMonth):
|
|
|
|
dailyEvents= \
|
2020-02-24 10:55:49 +00:00
|
|
|
getTodaysEvents(baseDir,nickname,domain, \
|
|
|
|
year,monthNumber,d)
|
2020-02-22 19:11:51 +00:00
|
|
|
if dailyEvents:
|
|
|
|
if dailyEvents.get(d):
|
|
|
|
newEvents={}
|
2020-02-24 10:55:49 +00:00
|
|
|
newEvents[d+(7-(dayNumber+6-lastDayOfMonth))]= \
|
|
|
|
dailyEvents[d]
|
2020-02-22 19:11:51 +00:00
|
|
|
events=mergeDicts(events,newEvents)
|
|
|
|
|
|
|
|
return events
|
2020-02-23 09:35:52 +00:00
|
|
|
|
2020-02-23 09:42:09 +00:00
|
|
|
def getCalendarEvents(baseDir: str,nickname: str,domain: str, \
|
|
|
|
year: int,monthNumber: int) -> {}:
|
2020-02-23 09:35:52 +00:00
|
|
|
"""Retrieves calendar events
|
2020-02-24 10:55:49 +00:00
|
|
|
Returns a dictionary indexed by day number of lists containing
|
|
|
|
Event and Place activities
|
2020-02-23 09:35:52 +00:00
|
|
|
"""
|
2020-02-23 09:45:04 +00:00
|
|
|
calendarFilename= \
|
|
|
|
baseDir+'/accounts/'+nickname+'@'+domain+ \
|
|
|
|
'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt'
|
|
|
|
|
2020-02-23 09:35:52 +00:00
|
|
|
events={}
|
|
|
|
if not os.path.isfile(calendarFilename):
|
|
|
|
return events
|
2020-02-23 09:45:04 +00:00
|
|
|
|
2020-02-23 09:35:52 +00:00
|
|
|
calendarPostIds=[]
|
|
|
|
recreateEventsFile=False
|
|
|
|
with open(calendarFilename,'r') as eventsFile:
|
|
|
|
for postId in eventsFile:
|
|
|
|
postId=postId.replace('\n','')
|
|
|
|
postFilename=locatePost(baseDir,nickname,domain,postId)
|
|
|
|
if not postFilename:
|
|
|
|
recreateEventsFile=True
|
2020-02-23 09:42:09 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
|
2020-02-23 09:42:09 +00:00
|
|
|
postJsonObject=loadJson(postFilename)
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningPost(postJsonObject):
|
2020-02-23 09:42:09 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
postEvent=[]
|
|
|
|
dayOfMonth=None
|
|
|
|
for tag in postJsonObject['object']['tag']:
|
2020-02-24 11:10:48 +00:00
|
|
|
if not isHappeningEvent(tag):
|
2020-02-23 09:42:09 +00:00
|
|
|
continue
|
2020-02-24 11:10:48 +00:00
|
|
|
# this tag is an event or a place
|
2020-02-23 09:42:09 +00:00
|
|
|
if tag['type']=='Event':
|
|
|
|
# tag is an event
|
|
|
|
if not tag.get('startTime'):
|
|
|
|
continue
|
|
|
|
eventTime= \
|
|
|
|
datetime.strptime(tag['startTime'], \
|
|
|
|
"%Y-%m-%dT%H:%M:%S%z")
|
|
|
|
if int(eventTime.strftime("%Y"))==year and \
|
|
|
|
int(eventTime.strftime("%m"))==monthNumber:
|
|
|
|
dayOfMonth=str(int(eventTime.strftime("%d")))
|
|
|
|
postEvent.append(tag)
|
|
|
|
else:
|
|
|
|
# tag is a place
|
|
|
|
postEvent.append(tag)
|
|
|
|
|
|
|
|
if postEvent and dayOfMonth:
|
|
|
|
calendarPostIds.append(postId)
|
|
|
|
if not events.get(dayOfMonth):
|
|
|
|
events[dayOfMonth]=[]
|
|
|
|
events[dayOfMonth].append(postEvent)
|
2020-02-23 09:35:52 +00:00
|
|
|
|
|
|
|
# if some posts have been deleted then regenerate the calendar file
|
|
|
|
if recreateEventsFile:
|
|
|
|
calendarFile=open(calendarFilename, "w")
|
|
|
|
for postId in calendarPostIds:
|
|
|
|
calendarFile.write(postId+'\n')
|
|
|
|
calendarFile.close()
|
|
|
|
|
|
|
|
return events
|
2020-02-23 13:28:27 +00:00
|
|
|
|
|
|
|
def removeCalendarEvent(baseDir: str,nickname: str,domain: str, \
|
|
|
|
year: int,monthNumber: int,messageId: str) -> None:
|
|
|
|
"""Removes a calendar event
|
|
|
|
"""
|
|
|
|
calendarFilename= \
|
|
|
|
baseDir+'/accounts/'+nickname+'@'+domain+ \
|
|
|
|
'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt'
|
|
|
|
if not os.path.isfile(calendarFilename):
|
|
|
|
return
|
|
|
|
if '/' in messageId:
|
|
|
|
messageId=messageId.replace('/','#')
|
|
|
|
if messageId not in open(calendarFilename).read():
|
|
|
|
return
|
|
|
|
lines=None
|
|
|
|
with open(calendarFilename, "r") as f:
|
|
|
|
lines = f.readlines()
|
|
|
|
if not lines:
|
|
|
|
return
|
|
|
|
with open(calendarFilename, "w+") as f:
|
|
|
|
for line in lines:
|
|
|
|
if messageId not in line:
|
|
|
|
f.write(line)
|