diff --git a/utils.py b/utils.py index 7f29924c..059b306d 100644 --- a/utils.py +++ b/utils.py @@ -11,6 +11,7 @@ import time import shutil import datetime import json +from calendar import monthrange def removeAvatarFromCache(baseDir: str,actorStr: str) -> None: """Removes any existing avatar entries from the cache @@ -584,3 +585,17 @@ def fileLastModified(filename: str) -> str: t = os.path.getmtime(filename) modifiedTime=datetime.datetime.fromtimestamp(t) return modifiedTime.strftime("%Y-%m-%dT%H:%M:%SZ") + +def daysInMonth(year: int,monthNumber: int) -> int: + """Returns the number of days in the month + """ + if monthNumber<1 or monthNumber>12: + return None + daysRange=monthrange(year, monthNumber) + return daysRange[1] + +def mergeDicts(dict1: {}, dict2: {}) -> {}: + """Merges two dictionaries + """ + res = {**dict1, **dict2} + return res diff --git a/webinterface.py b/webinterface.py index 5a5fd8c7..74c97454 100644 --- a/webinterface.py +++ b/webinterface.py @@ -23,6 +23,8 @@ from pgp import getPGPpubKey from xmpp import getXmppAddress from matrix import getMatrixAddress from donate import getDonationUrl +from utils import daysInMonth +from utils import mergeDicts from utils import updateRecentPostsCache from utils import getNicknameFromActor from utils import getDomainFromActor @@ -3672,17 +3674,24 @@ def getCalendarEvents(baseDir: str,nickname: str,domain: str,year: int,monthNumb return events -def getTodaysEvents(baseDir: str,nickname: str,domain: str,dayOfMonth=None) -> {}: +def getTodaysEvents(baseDir: str,nickname: str,domain: str, \ + currYear=None,currMonthNumber=None,currDayOfMonth=None) -> {}: """Retrieves calendar events for today Returns a dictionary of lists containing Event and Place activities """ now=datetime.now() - year=now.year - monthNumber=now.month - if not dayOfMonth: + 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=dayOfMonth + dayNumber=currDayOfMonth calendarFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt' events={} if not os.path.isfile(calendarFilename): @@ -3743,6 +3752,92 @@ def getTodaysEvents(baseDir: str,nickname: str,domain: str,dayOfMonth=None) -> { return events +def getThisWeeksEvents(baseDir: str,nickname: str,domain: str) -> {}: + """Retrieves calendar events for this week + Returns a dictionary indexed by day number of lists containing Event and Place activities + """ + now=datetime.now() + year=now.year + monthNumber=now.month + dayNumber=now.day + calendarFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/calendar/'+str(year)+'/'+str(monthNumber)+'.txt' + events={} + if not os.path.isfile(calendarFilename): + return events + 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 + else: + postJsonObject=loadJson(postFilename) + if not postJsonObject: + continue + if not postJsonObject.get('object'): + continue + if not isinstance(postJsonObject['object'], dict): + continue + if not postJsonObject['object'].get('tag'): + continue + + postEvent=[] + dayOfMonth=None + weekDayIndex=None + for tag in postJsonObject['object']['tag']: + if not tag.get('type'): + continue + if tag['type']!='Event' and tag['type']!='Place': + continue + 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 and \ + (int(eventTime.strftime("%d"))>=dayNumber and \ + int(eventTime.strftime("%d"))<=dayNumber+6): + dayOfMonth=str(int(eventTime.strftime("%d"))) + weekDayIndex=dayOfMonth-dayNumber + postEvent.append(tag) + 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) + + # 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= \ + getTodaysEvents(baseDir,nickname,domain,year,monthNumber,d) + if dailyEvents: + if dailyEvents.get(d): + newEvents={} + newEvents[d+(7-(dayNumber+6-lastDayOfMonth))]=dailyEvents[d] + events=mergeDicts(events,newEvents) + + return events + def htmlCalendarDay(translate: {}, \ baseDir: str,path: str, \ year: int,monthNumber: int,dayNumber: int,