def prepareVobj(view, uuid, recordSet, vobjs): """ Determine if a recordset is for a vtodo, or a vevent, then create it. Modifications may not have event records OR task records, so for modifications, check what was done for the master. This relies on recordsets for masters being processed before modifications. """ master_uuid, recurrenceID = translator.splitUUID(view, uuid) if recurrenceID is None: note, event = hasNoteOrEvent(recordSet) else: if vobjs.get(master_uuid).name.lower() == 'vevent': task, event = False, True else: task, event = True, False if event: vevent = vobject.newFromBehavior('vevent') vevent.isNative = True vobjs[uuid] = vevent else: # @@@ assert note? vtodo = vobject.newFromBehavior('vtodo') vtodo.isNative = True vobjs[uuid] = vtodo
def __init__(self, invitation, resp, email): # create ans = vobject.newFromBehavior('vcalendar') ans.add('method') ans.method.value = "REPLY" ans.add('vevent') for i in ["uid", "summary", "dtstart", "dtend", "organizer"]: if i in invitation.vevent.contents: ans.vevent.add( invitation.vevent.contents[i][0] ) # new timestamp ans.vevent.add('dtstamp') ans.vevent.dtstamp.value = datetime.utcnow().replace(tzinfo = invitation.vevent.dtstamp.value.tzinfo) ans.vevent.add('attendee') ans.vevent.attendee_list.pop() if 'attendee' in invitation.vevent.contents: atts = invitation.vevent.contents['attendee'] for a in atts: if self._get_email(a) == email: ans.vevent.attendee_list.append(self._set_resp(a,resp)) self.ans = ans
def __init__(self, app, time_limit=None): job_base.TimeLimitedJob.__init__(self, app, time_limit) self.app = app self.calendar_change_count = 0 self.count = 0 self.vobject_calendar = vobject.newFromBehavior('vcalendar') self.app.calendar = None self.app.calendar_lock = threading.Lock()
def generate_response_for(invite): #cal = vobject.iCalendar() rsp = vobject.newFromBehavior('vcalendar') rsp.add('method') rsp.method.value = "REPLY" rsp.add('vevent') for key in ['uid', 'summary', 'dtstart', 'dtend', 'organizer']: if invite.vevent.contents.has_key(key): rsp.vevent.add(invite.vevent.contents[key][0]) rsp.vevent.add('dtstamp') rsp.vevent.dtstamp.value = datetime.utcnow().replace( tzinfo = invite.vevent.dtstamp.value.tzinfo) return rsp
def get_answer(invitation): # create ans = vobject.newFromBehavior('vcalendar') ans.add('method') ans.method.value = "REPLY" ans.add('vevent') # just copy from invitation for i in ["uid", "summary", "dtstart", "dtend", "organizer"]: if invitation.vevent.contents.has_key(i): ans.vevent.add( invitation.vevent.contents[i][0] ) # new timestamp ans.vevent.add('dtstamp') ans.vevent.dtstamp.value = datetime.utcnow().replace( tzinfo = invitation.vevent.dtstamp.value.tzinfo) return ans
def get_answer(invitation): # create ans = vobject.newFromBehavior('vcalendar') ans.add('method') ans.method.value = "REPLY" ans.add('vevent') # just copy from invitation for i in ["uid", "summary", "dtstart", "dtend", "organizer"]: if invitation.vevent.contents.has_key(i): ans.vevent.add(invitation.vevent.contents[i][0]) # new timestamp ans.vevent.add('dtstamp') ans.vevent.dtstamp.value = datetime.utcnow().replace( tzinfo=invitation.vevent.dtstamp.value.tzinfo) return ans
def get_answer(invitation): # create ans = vobject.newFromBehavior('vcalendar') ans.add('method') ans.method.value = "REPLY" ans.add('vevent') # just copy from invitation #for i in ["uid", "summary", "dtstart", "dtend", "organizer"]: # There's a problem serializing TZ info in Python, temp fix for i in ["uid", "summary", "organizer"]: if i in invitation.vevent.contents: ans.vevent.add( invitation.vevent.contents[i][0] ) # new timestamp ans.vevent.add('dtstamp') ans.vevent.dtstamp.value = datetime.utcnow().replace( tzinfo = invitation.vevent.dtstamp.value.tzinfo) return ans
def upload_calendar(data): #Check if called from client side (not necessary) if (isinstance(data, str)): data = json.loads(data) #Connect to CalDav Account account = frappe.get_doc("CalDav Account", data["caldavaccount"]) """ account = data["caldavaccount"] """ client = caldav.DAVClient(url=account.url, username=account.username, password=account.password) principal = client.principal() calendars = principal.calendars() cal = None #Look for the right calendar for calendar in calendars: if (str(calendar) == data["calendarurl"]): cal = calendar #Go through events erp_events = frappe.db.sql(""" SELECT * FROM `tabEvent` WHERE icalendar = '{icalendar}' AND custom_pattern is NULL; """.format(icalendar=data["icalendar"]), as_dict=1) weekdays = [ "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" ] rrweekdays = [RR.MO, RR.TU, RR.WE, RR.TH, RR.FR, RR.SA, RR.SU] upstats = { "10a": 0, "10b": 0, "10c": 0, "11b": 0, "not_uploadable": 0, "cancelled_or_closed_of_no_uploadable": 0, "exceptions": 0, } rstats = { "mapped": 0, "not_mapped": 0, } #Error Stack error_stack = [] for idx, ee in enumerate(erp_events): uploadable = True try: print(ee) #Case 10a: Status Open, everything nominal if (ee["status"] == "Open"): new_calendar = vobject.newFromBehavior('vcalendar') e = new_calendar.add('vevent') e.add('summary').value = ee["subject"] dtstart = ee["starts_on"] e.add('dtstart').value = dtstart e.add('description').value = ee["description"] if (ee["event_type"] in ["Public", "Private", "Confidential"]): e.add('class').value = ee["event_type"] #Case 10b: Status Open, but Event Type is Cancelled elif (ee["event_type"] == "Cancelled"): uploadable = False upstats["10b"] += 1 #Case 10c: Status Open, but Event Type not in [Public, Private, Confidential,Cancelled] else: uploadable = False upstats["10c"] += 1 raise Exception( 'Exception:', 'Event with Name ' + ee["name"] + ' has the invalid Event Type ' + ee["event_type"]) dtend = ee["ends_on"] if (dtend == None): dtend = dtstart + datetime.timedelta(minutes=15) frappe.db.set_value('Event', ee["name"], 'ends_on', dtend, update_modified=False) if (ee["all_day"] == 0): e.add('dtend').value = dtend else: e.dtstart.value = dtstart.date() dtend = (dtend.date() + datetime.timedelta(days=1)) e.add('dtend').value = dtend if (ee["last_modified"] == None): frappe.db.set_value('Event', ee["name"], 'last_modified', ee["modified"].replace(microsecond=0), update_modified=False) e.add('last-modified').value = ee["modified"].replace( microsecond=0) else: e.add('last-modified').value = ee["last_modified"] if (ee["created_on"] == None): frappe.db.set_value('Event', ee["name"], 'created_on', ee["creation"].replace(microsecond=0), update_modified=False) e.add('created').value = ee["creation"].replace( microsecond=0) else: e.add('created').value = ee["created_on"] #Create rrule rrule = None until = ee["repeat_till"] byweekday = [] if (ee["repeat_this_event"] == 1 and ee["repeat_till"] != None): until = datetime.datetime(until.year, until.month, until.day, dtstart.hour, dtstart.minute, dtstart.second) if (ee["repeat_on"] == "Daily"): rrule = RR.rrule(freq=RR.DAILY, until=until) elif (ee["repeat_on"] == "Weekly"): for idx, weekday in enumerate(weekdays): if (ee[weekday] == 1): byweekday.append(rrweekdays[idx]) rrule = RR.rrule(freq=RR.WEEKLY, until=until, byweekday=byweekday) elif (ee["repeat_on"] == "Monthly"): rrule = RR.rrule(freq=RR.MONTHLY, until=until) elif (ee["repeat_on"] == "Yearly"): rrule = RR.rrule(freq=RR.YEARLY, until=until) if (rrule != None): e.add('rrule').value = rrule rstats["mapped"] += 1 else: rstats["not_mapped"] += 1 #Remove None Children none_attributes = [] for child in e.getChildren(): if (child.value == None): none_attributes.append(child.name.lower()) for attr in none_attributes: e.__delattr__(attr) ics = new_calendar.serialize() print(ics) frappe.db.set_value('Event', ee["name"], 'uid', e.uid.value, update_modified=False) #Upload if (uploadable): cal.save_event(ics) upstats["10a"] += 1 else: upstats["not_uploadable"] += 1 #Case 11a: Status != Open else: uploadable = False upstats["11b"] += 1 except Exception as ex: #traceback.print_exc() tb = traceback.format_exc() upstats["exceptions"] += 1 error_stack.append({ "message": "Could not upload event. Exception: \n" + tb, "event": json.dumps(ee) }) #Update UI percent_progress = idx / len(erp_events) * 100 frappe.publish_progress(percent=percent_progress, title="Uploading") #Return JSON and Log message = {} upstats["cancelled_or_closed_of_no_uploadable"] = upstats[ "not_uploadable"] - upstats["10b"] - upstats["11b"] message["upstats"] = upstats message["rstats"] = rstats message["error_stack"] = error_stack """ """ d = frappe.get_doc("iCalendar", data["icalendar"]) d.last_sync_log = json.dumps(message) d.save() d.add_comment('Comment', text="Stats:\n" + str(upstats) + "\nRRule Stats:\n" + str(rstats)) """ """ return json.dumps(message)
def email_appointment(sender, to, message, cust_id, cust_name, cust_phone, cmp_name, begin, duration, member_name): ''' Create and send email with iCalendar event attached ''' # Create email msg = Message() msg['Subject'] = u'RDV Call center Multimédia %s' % cust_name msg['To'] = to msg['From'] = sender msg['Content-class'] = 'urn:content-classes:calendarmessage' msg['Content-type'] = 'text/calendar; method=REQUEST; charset=UTF-8' msg['Content-transfer-encoding'] = '8BIT' # vCal (vobject automatically adds missing fields, eg. UUID) vcal = vobject.newFromBehavior('vcalendar') vcal.add('method').value = u'REQUEST' vcal.add('vevent') vcal.add('prodid').value = '-//SysNux.pf/NONSGML AstPortal V1.0//EN' vcal.add('version').value = '2.0' vcal.vevent.add('description').value = u'''Rendez-vous fixé par le Call Center Multimédia pour la campagne "%s" Client n°%s / %s N° de téléphone : %s Message : ----- %s ----- Observations particulières : NB : Cet événement est envoyé à titre d'information et ne nécessite pas de retour. Merci et bonne réception %s ''' % (cmp_name, cust_id, cust_name, cust_phone, message, member_name) vcal.vevent.add('dtstart').value = begin vcal.vevent.add('dtend').value = begin + timedelta(0, duration*60) vcal.vevent.add('class').value = u'PUBLIC' vcal.vevent.add('dtstamp').value = datetime.now() vcal.vevent.add('created').value = datetime.now() vcal.vevent.add('last-modified').value = datetime.now() vcal.vevent.add('organizer').value = u'mailto:%s' % sender vcal.vevent.add('attendee').value = u'mailto:%s' % to vcal.vevent.add('transp').value = 'OPAQUE' vcal.vevent.add('summary').value = u'RDV %s' % cust_name vcal.add('vtimezone') vcal.vtimezone.add('tzid').value = 'Pacific/Tahiti' vcal.vtimezone.add('x-lic-location').value = 'Pacific/Tahiti' vcal.vtimezone.add('standard') vcal.vtimezone.standard.add('TZOFFSETFROM').value = '-1000' vcal.vtimezone.standard.add('TZOFFSETTO').value = '-1000' vcal.vtimezone.standard.add('TZNAME').value = 'TAHT' vcal.vtimezone.standard.add('DTSTART').value = datetime(1970,1,1) # valarm = vobject.newFromBehavior('VALARM') # valarm.add('trigger').value = timedelta(-1) # valarm.add('action').value = 'email' # valarm.add('attendee').value = to # valarm.add('summary').value = 'Rappel RDV %s' % cust_name # valarm.add('description').value = 'RDV dans 24 heures avec client %s' % cust_id # vcal.vevent.add(valarm) log.debug(vcal.prettyPrint()) msg.set_payload(vcal.serialize()) # Send email log.debug(msg.as_string()) s = smtplib.SMTP() try: s.connect('localhost') s.sendmail(sender, to, msg.as_string()) s.close() except: flash(u'Une erreur est survenue, l\'email n\'a pu être envoyé', 'error')
write_cur.execute('INSERT INTO calendars (principaluri, displayname, uri, ctag, description, calendarorder, calendarcolor, timezone, components) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)', var) calendarid = write_cur.lastrowid else: calendarid = row[0] # Clear calendar first write_cur.execute('DELETE FROM calendarobjects WHERE calendarid = %s', [calendarid]) read_cur.execute('SELECT c.carddata, c.uri FROM cards as c JOIN addressbooks as a ON c.addressbookid = a.id WHERE a.principaluri = %s', [uri]) for row in read_cur.fetchall(): card = vobject.readOne(row[0]) carduri = row[1] if hasattr(card, 'bday'): bday = datetime.strptime(card.bday.value, '%Y-%m-%d').date() ca = vobject.newFromBehavior('vcalendar') # Create event ev = ca.add('vevent') ev.add('summary').value = card.fn.value ev.add('dtstart').value = bday ev.add('dtend').value = bday+timedelta(days=1) ev.add('class').value = "public" ev.add('created').value = now ev.add('dtstamp').value = now ev.add('last-modified').value = now ev.add('rrule').value = "FREQ=YEARLY;BYMONTHDAY="+str(bday.day)+";BYMONTH="+str(bday.month); ev.add('transp').value = "TRANSPARENT" ev.add('categories').value = ["Birthday"] ev.add('x-microsoft-cdo-alldayevent').value = "TRUE"
import vobject cal = vobject.newFromBehavior('vcalendar') cal.behavior print(cal)