almanaque.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. #All code is GPLv3 by Alejandro <alkeon@autistici.org> Castilla
  4. #El miedo cambia de bando como de la noche al día
  5. from icalendar import Calendar, Event
  6. from event_day import event_day
  7. from datetime import datetime, timedelta
  8. from dateutil.relativedelta import relativedelta
  9. from dateutil.rrule import rrule, MONTHLY, weekday
  10. from basic_event import basic_event
  11. from math import floor
  12. from pytz import UTC
  13. from cryptography.fernet import Fernet
  14. from cryptography.hazmat.backends import default_backend
  15. import operator
  16. import warnings
  17. import os
  18. import sys
  19. weekdays = ['MO','TU','WE','TH','FR','SA','SU']
  20. # - allow different filenames
  21. class Almanaque:
  22. def __init__(self):
  23. self.event_list = list()
  24. self.password = None
  25. def read_password(self):
  26. try:
  27. g = open('pass', "r")
  28. self.password = g.read()
  29. g.close()
  30. return True
  31. except:
  32. return False
  33. def help(self):
  34. print("uses: ")
  35. print("almanaque.py -n \t Add new entry")
  36. print("almanaque.py -c \t Change entry")
  37. print("almanaque.py -s \"DD\" \t Show events for that day")
  38. print("almanaque.py -s \"DD-MM\" \t Show events for that day")
  39. print("almanaque.py -s \"DD-MM-YYYY\" \t Show events for that day")
  40. print("almanaque.py -d \t Check events")
  41. print("almanaque.py -i \t Import calendar")
  42. print("almanaque.py -e \t Export calendar")
  43. print("almanaque.py -a NAME \t Print all about event with name")
  44. print("almanaque.py --daemon \t Run as daemon")
  45. print("almanaque.py --help \t Show this help")
  46. def check_arguments(self):
  47. if(self.read_password()):
  48. self.load()
  49. elif(not self.load()):
  50. key = Fernet.generate_key()
  51. print("Key not found.")
  52. print("Do you want to use this random generated key: " + key.decode('utf-8'))
  53. print("0.- No")
  54. print("1.- Yes")
  55. option = input()
  56. if(option):
  57. self.password = key.decode('utf-8')
  58. g = open('pass', "wb")
  59. g.write(key)
  60. g.close()
  61. if(len(sys.argv) == 2):
  62. if(sys.argv[1] == "-d"):
  63. name = input("Write event name\n")
  64. self.delete_event(name)
  65. self.save()
  66. elif(sys.argv[1] == "-c"):
  67. name = input("Write event name\n")
  68. self.delete_event(name)
  69. self.save()
  70. elif(sys.argv[1] == "-n"):
  71. event = self.create_event()
  72. self.insert_event(event)
  73. self.save()
  74. elif(sys.argv[1] == "-i"):
  75. self.event_list.clear()
  76. self.import_calendar()
  77. self.save()
  78. elif(sys.argv[1] == "-e"):
  79. self.export_calendar()
  80. elif(sys.argv[1] == "--daemon"):
  81. self.daemon()
  82. elif(sys.argv[1] == "-h" or sys.argv[1] == "--help"):
  83. self.help()
  84. else:
  85. if(len(sys.argv) == 3 and sys.argv[1] == "-s"):
  86. if(len(sys.argv[2]) == 10):
  87. start = datetime.strptime(sys.argv[2], '%d-%m-%Y')
  88. elif(len(sys.argv[2]) == 5):
  89. today = datetime.now()
  90. start = datetime(today.year, int(sys.argv[2][3:5]), int(sys.argv[2][:2]))
  91. else:
  92. today = datetime.now()
  93. start = datetime(today.year ,today.month, int(sys.argv[2][:2]))
  94. self.check_list(start)
  95. elif(len(sys.argv) == 3 and sys.argv[1] == "-a"):
  96. self.show_event(sys.argv[2])
  97. else:
  98. self.check_list(datetime.today())
  99. def load(self):
  100. try:
  101. g = open('calendar.sics', "rb")
  102. if(self.password is None):
  103. self.password = input("Write password")
  104. f = Fernet(bytes(self.password, 'utf-8'))
  105. try:
  106. file_decrypted = f.decrypt(g.read())
  107. gcal = Calendar.from_ical(file_decrypted.decode("utf-8") )
  108. for component in gcal.walk():
  109. if(component.name == "VEVENT"):
  110. summary = str(component.get('summary'))
  111. start = datetime.strptime(component.get('dtstart').to_ical().decode('utf-8'), '%Y%m%dT%H%M%S')
  112. end = datetime.strptime(component.get('dtend').to_ical().decode('utf-8'), '%Y%m%dT%H%M%S')
  113. stamp = datetime.strptime(component.get('dtstamp').to_ical().decode('utf-8'), '%Y%m%dT%H%M%SZ')
  114. event = basic_event(summary, start, stamp, component.get('rrule'),end)
  115. self.event_list.append(event)
  116. g.close()
  117. return True
  118. except:
  119. print("Calendar not loaded. Maybe encryption")
  120. g.close()
  121. return False
  122. except:
  123. print("calendar file not loaded")
  124. return False
  125. def change_event(self):
  126. i = 0
  127. hasEnded = True
  128. while(i < len(self.event_list) and hasEnded):
  129. if(self.event_list[i].name.find(name) >= 0):
  130. print("Wanna change this event?")
  131. print(self.event_list[i].name)
  132. print(self.event_list[i].start)
  133. print(self.event_list[i].rrule)
  134. option = input("0.- No\n1.- Yes\n2.- Stop\n")
  135. if(int(option) == 1):
  136. hasEnded = False
  137. self.event_list[i] = self.create_event()
  138. if(int(option) == 2):
  139. hasEnded = False
  140. i += 1
  141. def import_calendar(self):
  142. g = open('import_calendar.ics', "rb")
  143. gcal = Calendar.from_ical(g.read() )
  144. for component in gcal.walk():
  145. if component.name == "VEVENT":
  146. summary = str(component.get('summary'))
  147. start = datetime.strptime(component.get('dtstart').to_ical().decode('utf-8'), '%Y%m%dT%H%M%S')
  148. end = datetime.strptime(component.get('dtend').to_ical().decode('utf-8'), '%Y%m%dT%H%M%S')
  149. stamp = datetime.strptime(component.get('dtstamp').to_ical().decode('utf-8'), '%Y%m%dT%H%M%SZ')
  150. event = basic_event(summary, start, stamp, component.get('rrule'),end)
  151. self.event_list.append(event)
  152. g.close()
  153. self.save()
  154. def show_event(self, name):
  155. i = 0
  156. while(i < len(self.event_list)):
  157. if(self.event_list[i].name.find(name) >= 0):
  158. print(self.event_list[i].name)
  159. print(self.event_list[i].start)
  160. print(self.event_list[i].end)
  161. print(self.event_list[i].rrule)
  162. i += 1
  163. def save(self):
  164. cal = self.events_to_calendar()
  165. f = open('calendar.sics', 'wb')
  166. if(self.password is None):
  167. password = input("Write password")
  168. while(password != input("Repeat password")):
  169. password = input("Repeat password")
  170. else:
  171. password = self.password
  172. fer = Fernet(bytes(password, 'utf-8'))
  173. f.write(fer.encrypt(cal.to_ical()))
  174. f.close()
  175. def export_calendar(self):
  176. cal = self.events_to_calendar()
  177. f = open('exported_calendar.ics', 'wb')
  178. f.write(cal.to_ical())
  179. f.close()
  180. def events_to_calendar(self):
  181. cal = Calendar()
  182. cal.add('prodid', '-//Almanaque//')
  183. cal.add('version', '2.0')
  184. i = 0
  185. while(i < len(self.event_list)):
  186. event = Event()
  187. event.add('summary', self.event_list[i].get_name())
  188. event.add('dtstart', self.event_list[i].get_start())
  189. event.add('dtend', self.event_list[i].get_end())
  190. event.add('dtstamp', self.event_list[i].get_stamp())
  191. if(self.event_list[i].get_rrule() is not None):
  192. event.add('rrule', self.event_list[i].get_rrule())
  193. cal.add_component(event)
  194. i += 1
  195. return cal
  196. def daemon(self):
  197. i = 0
  198. while(i < len(self.event_list)):
  199. isToday = self.check_day(datetime.today(), i)
  200. if(isToday):
  201. self.notify("Today", self.event_list[i].name)
  202. if('COUNT' in self.event_list[i].rrule):
  203. self.event_list[i].rrule['COUNT'][0] = str(
  204. int(self.event_list[i].rrule['COUNT'][0]) - 1)
  205. isTomorrow = self.check_day(datetime.today() + timedelta(1) , i)
  206. if(isTomorrow):
  207. self.notify("Tomorrow", self.event_list[i].name)
  208. i += 1
  209. def create_event(self):
  210. summary = input("Write event description ")
  211. start_day = input("Write start day ")
  212. start_month = input("Write start month ")
  213. start_year = input("Write start year ")
  214. hour_and_minutes = input("Wanna write time also?\n0.- No\n1.- Yes\n")
  215. if(hour_and_minutes == "1"):
  216. start_hour = input("Write start hour ")
  217. start_minutes = input("Write start minute ")
  218. if(start_hour == ""):
  219. start_hour = today.hour;
  220. else:
  221. start_hour = int(start_hour)
  222. if(start_minutes == ""):
  223. start_minutes = today.minute;
  224. else:
  225. start_minutes = int(start_minutes)
  226. today = datetime.today()
  227. if(start_day == ""):
  228. start_day = today.day;
  229. else:
  230. start_day = int(start_day)
  231. if(start_month == ""):
  232. start_month = today.month;
  233. else:
  234. start_month = int(start_month)
  235. if(start_year == ""):
  236. start_year = today.year;
  237. else:
  238. start_year = int(start_year)
  239. end_day = ""
  240. end_month = ""
  241. end_year = ""
  242. rrule = {}
  243. option_one_day = True
  244. frequency = input("0.- SECONDLY\n1.- MINUTELY\n2.- HOURLY\n3.- DAILY\n4.- WEEKLY\n5.- MONTHLY\n6.- YEARLY\nn.- No\n")
  245. if(frequency != 'n'):
  246. frequency = int(frequency)
  247. if(frequency == 0):
  248. rrule['FREQ'] = ['SECONDLY']
  249. if(frequency == 1):
  250. rrule['FREQ'] = ['MINUTELY']
  251. if(frequency == 2):
  252. rrule['FREQ'] = ['HOURLY']
  253. if(frequency == 3):
  254. rrule['FREQ'] = ['DAILY']
  255. if(frequency == 4):
  256. rrule['FREQ'] = ['WEEKLY']
  257. if(frequency == 5):
  258. rrule['FREQ'] = ['MONTHLY']
  259. if(frequency == 6):
  260. rrule['FREQ'] = ['YEARLY']
  261. print("Want detailed options?")
  262. print("0.- No")
  263. print("1.- Yes")
  264. detailed = int(input())
  265. if(detailed):
  266. option_one_day = int(input("One day event\n0.- No\n1.- Yes\n"))
  267. if(not option_one_day):
  268. end_day = int(input("Write end day "))
  269. end_month = int(input("Write end month "))
  270. end_year = int(input("Write end year "))
  271. count = int(input("Ocurrences of event (use 0 for None)\n"))
  272. if(count > 0):
  273. rrule['COUNT'] = count
  274. option_until = int(input("Limited by a date\n0.- No\n1.- Yes\n"))
  275. if(option_until):
  276. day = int(input("Limiting day "))
  277. month = int(input("Limiting month "))
  278. year = int(input("Limiting year "))
  279. date = datetime(year=year, month=month, day=day)
  280. rrule['UNTIL'] = date
  281. interval = int(input("Interval of repeat (use 0 for None)\n"))
  282. if(interval > 0 and interval < 10):
  283. rrule['INTERVAL'] = interval
  284. bymonth = input("Limit by month\n type n to no\n")
  285. if(bymonth != 'n'):
  286. bymonth = int(bymonth)
  287. rrule['BYMONTH'] = []
  288. while(bymonth >= 0 and bymonth < 13):
  289. rrule['BYMONTH'].append(bymonth)
  290. bymonth = int(input("Limit by month\n"))
  291. bymonthday = input("Limit by month day\n type n to no\n")
  292. if(bymonthday != 'n'):
  293. bymonthday = int(bymonthday)
  294. rrule['BYMONTHDAY'] = []
  295. while(bymonthday >= 0 and bymonthday < 32):
  296. rrule['BYMONTHDAY'].append(bymonthday)
  297. bymonthday = int(input("Limit by month day\n"))
  298. byday = input("Limit by day\n type n to no\n")
  299. if(byday != 'n'):
  300. i = 1
  301. rrule['BYDAY'] = [weekdays[int(byday[0])]]
  302. while(i < len(byday)):
  303. rrule['BYDAY'].append(weekdays[int(byday[i])])
  304. i += 1
  305. bysecond = input("Limit by second\n type n to no\n")
  306. if(bysecond != 'n'):
  307. bysecond = int(bysecond)
  308. rrule['BYSECOND'] = []
  309. while(bysecond >= 0 and bysecond <= 59):
  310. rrule['BYSECOND'].append(bysecond)
  311. bysecond = input("Limit by second\n");
  312. bysecond = int(bysecond)
  313. byweekno = input("Limit by week\n type n to no\n")
  314. if(byweekno != 'n'):
  315. i = 1
  316. rrule['BYWEEKNO'] = [int(byweekno[0])]
  317. while(i < len(byweekno)):
  318. rrule['BYWEEKNO'].append(int(byweekno[i]))
  319. i += 1
  320. byyearday = input("Limit by day of the year\n type n to no\n")
  321. if(byyearday != 'n'):
  322. byyearday = int(byyearday)
  323. rrule['BYYEARDAY'] = []
  324. while(byyearday >= 0 and byyearday < 367):
  325. rrule['BYYEARDAY'].append(byyearday)
  326. byyearday = input("Limit by day of the year\n");
  327. byyearday = int(byyearday)
  328. if(hour_and_minutes == "0"):
  329. startt = datetime(year=start_year, month=start_month, day=start_day)
  330. else:
  331. startt = datetime(year=start_year, month=start_month, day=start_day, hour= start_hour, minute=start_minutes)
  332. if(option_one_day):
  333. event = basic_event(summary, startt, datetime.today(), rrule)
  334. else:
  335. endt = datetime(year=end_year, month=end_month, day=end_day)
  336. event = basic_event(summary, startt, datetime.today(), rrule, endt)
  337. return event
  338. def insert_event(self, event):
  339. self.event_list.append(event)
  340. #Check end date
  341. def check_end(self, date, i):
  342. if(self.is_same_day(self.event_list[i].end, date)):
  343. return True
  344. elif(self.event_list[i].rrule is not None and 'FREQ' in self.event_list[i].rrule):
  345. if(not self.check_recurrence(date, i)):
  346. if(self.check_recurrence(date - timedelta(1), i)):
  347. return True
  348. else:
  349. return False
  350. else:
  351. return False
  352. else:
  353. return False
  354. def check_day(self, date, i):
  355. isToday = False
  356. greaterThanStart = False
  357. lesserThanEnd = False
  358. #Check if is it today
  359. if(self.event_list[i].start <= date):
  360. greaterThanStart = True
  361. if(self.event_list[i].end > date):
  362. lesserThanEnd = True
  363. isToday = greaterThanStart and lesserThanEnd
  364. if(greaterThanStart):
  365. #Check if is today by recurrence
  366. if((not isToday and self.event_list[i].rrule is not None and 'FREQ' in self.event_list[i].rrule) or isToday):
  367. return self.check_recurrence(date, i)
  368. #Throw notifications
  369. def notify(self, day, name):
  370. try:
  371. #Desktop notifications
  372. os.system("notify-send '"+ day +"' '" + name + "'")
  373. except:
  374. #Termux (Android)
  375. os.system("termux-notification --title '"+ day +"' --content '" + name + "'")
  376. def check_list(self, check_date):
  377. today_date = check_date
  378. print("Right now " + str(check_date))
  379. i = 0
  380. past_events = []
  381. today = []
  382. tomorrow = []
  383. next_events = []
  384. while(i < len(self.event_list)):
  385. #Load past events
  386. day = 0
  387. while(day < 8):
  388. isThisDay = self.check_end(today_date - timedelta(day), i)
  389. if(isThisDay):
  390. past_events.append(event_day(self.event_list[i], day))
  391. day += 1
  392. #Load today events
  393. isToday = self.check_day(today_date, i)
  394. if(isToday):
  395. if('COUNT' in self.event_list[i].rrule):
  396. self.event_list[i].rrule['COUNT'][0] = str(int(self.event_list[i].rrule['COUNT'][0]) - 1)
  397. today.append(self.event_list[i])
  398. #Load tomorrow events
  399. isTomorrow = self.check_day(today_date + timedelta(1), i)
  400. if(isTomorrow and not isToday):
  401. tomorrow.append(self.event_list[i])
  402. #Load next events
  403. day = 2
  404. while(day < 8):
  405. isThisDay = self.check_day(today_date + timedelta(day), i)
  406. if(isThisDay):
  407. next_events.append(event_day(self.event_list[i], day))
  408. day += 1
  409. i += 1
  410. #Show past events
  411. past_events.sort(key=operator.attrgetter('days'), reverse=True)
  412. i = 0
  413. if(len(past_events) > 0):
  414. print("---PAST EVENTS----")
  415. while(i < len(past_events)):
  416. print(past_events[i].event.name + " | " + str(past_events[i].days) + " days")
  417. i += 1
  418. #Show today events
  419. i = 0
  420. if(len(today) > 0):
  421. print("----TODAY EVENTS--")
  422. while(i < len(today)):
  423. print(today[i].name)
  424. i += 1
  425. #Show tomorrow events
  426. i = 0
  427. if(len(tomorrow) > 0):
  428. print("--TOMORROW EVENTS--")
  429. while(i < len(tomorrow)):
  430. print(tomorrow[i].name)
  431. i += 1
  432. #Show next events
  433. next_events.sort(key=operator.attrgetter('days'))
  434. i = 0
  435. if(len(next_events) > 0):
  436. print("-----NEXT EVENTS---")
  437. while(i < len(next_events)):
  438. print(next_events[i].event.name + " | " + str(next_events[i].days) + " days")
  439. i += 1
  440. #Check recurrence
  441. def check_recurrence(self, date, i):
  442. recurrence = True
  443. recurrence = recurrence and self.count(i)
  444. recurrence = recurrence and self.until(i, date)
  445. recurrence = recurrence and self.bymonth(i, date)
  446. recurrence = recurrence and self.bymonthday(i, date)
  447. recurrence = recurrence and self.byday(i, date)
  448. recurrence = recurrence and self.byyear(i, date)
  449. recurrence = recurrence and self.bysecond(i, date)
  450. recurrence = recurrence and self.byweekno(i, date)
  451. recurrence = recurrence and self.byyearday(i, date)
  452. recurrence = recurrence and self.freq(i, date)
  453. return recurrence
  454. #Check COUNT tag
  455. def count(self, i):
  456. if('COUNT' not in self.event_list[i].rrule):
  457. return True
  458. elif(int(self.event_list[i].rrule['COUNT'][0]) > 0):
  459. return True
  460. else:
  461. return False
  462. #Check UNTIL tag
  463. def until(self, i, date):
  464. if('UNTIL' not in self.event_list[i].rrule):
  465. return True
  466. elif (datetime.strptime(str(self.event_list[i].rrule['UNTIL']), '[datetime.datetime(%Y, %m, %d, %H, %M)]') > date):
  467. return True
  468. else:
  469. return False
  470. #Check BYMONTH tag
  471. def bymonth(self, i, date):
  472. if('BYMONTH' not in self.event_list[i].rrule):
  473. return True
  474. elif (self.event_list[i].rrule['BYMONTH'][0] == date.month):
  475. return True
  476. else:
  477. return False
  478. #Check BYMONTHDAY tag
  479. def bymonthday(self, i, date):
  480. if('BYMONTHDAY' not in self.event_list[i].rrule):
  481. return True
  482. elif (self.event_list[i].rrule['BYMONTHDAY'][0] == date.day):
  483. return True
  484. else:
  485. return False
  486. #Check BYDAY tag
  487. def byday(self, i, date):
  488. if('BYDAY' not in self.event_list[i].rrule):
  489. return True
  490. elif (self.check_byday_array(self.event_list[i].rrule['BYDAY'], date.weekday(), date)):
  491. return True
  492. else:
  493. return False
  494. def weekday_number_to_string(self, number):
  495. if(number == 0):
  496. return 'MO'
  497. elif(number == 1):
  498. return 'TU'
  499. elif(number == 2):
  500. return 'WE'
  501. elif(number == 3):
  502. return 'TH'
  503. elif(number == 4):
  504. return 'FR'
  505. elif(number == 5):
  506. return 'SA'
  507. elif(number == 6):
  508. return 'SU'
  509. else:
  510. return 'MO'
  511. def check_week_number(self, day_number, week_number, date):
  512. r = rrule(MONTHLY, count=1, byweekday=weekday(day_number),
  513. bysetpos=int(week_number), dtstart=date.replace(day=1))
  514. if(self.is_same_day(r[0], date)):
  515. return True
  516. else:
  517. return False
  518. def check_byday_array(self, array, day, date):
  519. result = False
  520. i = 0
  521. while(i < len(array)):
  522. week = True
  523. is_day = False
  524. if(array[i][0] == '1' or array[i][0] == '2' or array[i][0] == '3' or array[i][0] == '4' or array[i][0] == '5'):
  525. week = self.check_week_number(day, array[i][0], date)
  526. if(array[i] == self.weekday_number_to_string(day) or array[i][1:] == self.weekday_number_to_string(day)):
  527. is_day = True
  528. if(week and is_day):
  529. result = True
  530. i += 1
  531. return result
  532. #Check BYYEAR tag
  533. def byyear(self, i, date):
  534. if('BYYEAR' not in self.event_list[i].rrule):
  535. return True
  536. elif (self.event_list[i].rrule['BYYEAR'] == date.year):
  537. return True
  538. else:
  539. return False
  540. #Check BYSECOND tag
  541. def bysecond(self, i, date):
  542. if('BYSECOND' not in self.event_list[i].rrule):
  543. return True
  544. elif (self.event_list[i].rrule['BYSECOND'] == date.second):
  545. return True
  546. else:
  547. return False
  548. #Check BYWEEKNO tag
  549. def byweekno(self, i, date):
  550. if('BYWEEKNO' not in self.event_list[i].rrule):
  551. return True
  552. elif (self.event_list[i].rrule['BYWEEKNO'] == date.isocalendar()[1]):
  553. return True
  554. else:
  555. return False
  556. #Check BYYEARDAY tag
  557. def byyearday(self, i, date):
  558. if('BYYEARDAY' not in self.event_list[i].rrule):
  559. return True
  560. elif (self.event_list[i].rrule['BYYEARDAY'] == date.timetuple().tm_yday):
  561. return True
  562. else:
  563. return False
  564. #Check FREQ tag
  565. def freq(self, i, date):
  566. if('FREQ' not in self.event_list[i].rrule):
  567. return True
  568. elif ('YEARLY' in self.event_list[i].rrule['FREQ']):
  569. return self.freq_yearly(i, date)
  570. elif('MONTHLY' in self.event_list[i].rrule['FREQ']):
  571. return self.freq_monthly(i, date)
  572. elif('WEEKLY' in self.event_list[i].rrule['FREQ']):
  573. return self.freq_weekly(i, date)
  574. elif('DAILY' in self.event_list[i].rrule['FREQ']):
  575. is_valid = True
  576. if('INTERVAL' in self.event_list[i].rrule):
  577. if((date - self.event_list[i].start).days % self.event_list[i].rrule['INTERVAL'][0] != 0):
  578. return False
  579. else:
  580. return True
  581. else:
  582. return True
  583. else:
  584. return True
  585. #Check tags realted with FREQ when it's yearly
  586. def freq_yearly(self, i, date):
  587. is_valid = True
  588. if('INTERVAL' in self.event_list[i].rrule):
  589. years = self.event_list[i].start.year - date.year
  590. if(years % self.event_list[i].rrule['INTERVAL'][0] != 0):
  591. is_valid = is_valid and False
  592. if('BYMONTHDAY' in self.event_list[i].rrule):
  593. return is_valid
  594. if('BYDAY' in self.event_list[i].rrule):
  595. return is_valid
  596. elif(self.event_list[i].start.day == date.day and self.event_list[i].start.month == date.month):
  597. return is_valid
  598. else:
  599. return False
  600. #Check tags realted with FREQ when it's monthly
  601. def freq_monthly(self, i, date):
  602. is_valid = True
  603. if('INTERVAL' in self.event_list[i].rrule):
  604. date_without_time = datetime(self.event_list[i].start.year,
  605. self.event_list[i].start.month, self.event_list[i].start.day)
  606. date_without_time1 = datetime(date.year, date.month, date.day)
  607. r = relativedelta(date_without_time, date_without_time1)
  608. months = r.months + r.years * 12
  609. if(months % self.event_list[i].rrule['INTERVAL'][0] != 0):
  610. is_valid = is_valid and False
  611. if('BYDAY' in self.event_list[i].rrule):
  612. return is_valid
  613. elif(self.event_list[i].start.day == date.day):
  614. return is_valid
  615. else:
  616. return False
  617. #Check tags realted with FREQ when it's weekly
  618. def freq_weekly(self, i, date):
  619. is_valid = True
  620. if('INTERVAL' in self.event_list[i].rrule):
  621. weeks = (date - self.event_list[i].start).days / 7
  622. if(floor(weeks) % self.event_list[i].rrule['INTERVAL'][0] != 0):
  623. is_valid = is_valid and False
  624. if('BYDAY' in self.event_list[i].rrule):
  625. return is_valid and True
  626. elif (self.event_list[i].start.weekday() == date.weekday()):
  627. return is_valid and True
  628. else:
  629. return is_valid and False
  630. return is_valid
  631. def delete_event(self, name):
  632. i = 0
  633. hasEnded = False
  634. while(i < len(self.event_list) and not hasEnded):
  635. if(self.event_list[i].name.find(name) >= 0):
  636. print("Wanna delete this event?")
  637. print(self.event_list[i].name)
  638. print(self.event_list[i].start)
  639. print(self.event_list[i].rrule)
  640. option = input("0.- No\n1.- Yes\n2.- Stop\n")
  641. if(int(option) == 1):
  642. hasEnded = True
  643. self.event_list.pop(i)
  644. if(int(option) == 2):
  645. hasEnded = True
  646. i += 1
  647. def is_same_day(self, first_date, second_date):
  648. if(first_date.day == second_date.day and first_date.month == second_date.month and first_date.year == second_date.year):
  649. return True
  650. else:
  651. return False
  652. if __name__ == "__main__":
  653. a = Almanaque()
  654. a.check_arguments()