Verwendung von Twilio-, Python- und Google-Tools zur Automatisierung Ihrer Hochzeit

Der Autor des Artikels erzählt, wie er es geschafft hat, Programmierkenntnisse anzuwenden, um die Routineprozesse seines eigenen Hochzeitsereignisses zu automatisieren.

Für die meisten Menschen war der 3. September 2016 der häufigste Samstag, aber in meiner Erinnerung wird dieses Datum für immer bleiben, da meine Frau und ich an diesem Tag eine Hochzeit spielten.

Bild

Bei der Planung einer Hochzeit müssen Sie viele Punkte berücksichtigen: Essen, Dekoration und Dekoration, Tischlampen (ja, getrennt von Dekoration), Blumen, Unterkunft für Gäste, Transport, Unterhaltung und die Wahl des Veranstaltungsortes. Wenn Sie eine Hochzeit planen, sind Sie im Allgemeinen mit vielen Unbekannten konfrontiert, aber eines war ich mir sicher: Keine Hochzeit kann ohne eine ganze Reihe von Listen auskommen, verschachtelte Listen, die nicht bis zum Ende enden. Je mehr Listen vor meinen Augen schwebten, desto öfter begann ich darüber nachzudenken, wie ich den Vorbereitungsprozess verbessern könnte. Es war schmerzlich ineffizient und alle Arbeiten wurden manuell ausgeführt. Ich war mir sicher, dass Technologie sicherlich dazu beitragen könnte, zumindest einige der Punkte zu verbessern.

Sie werden überrascht sein zu erfahren, dass das Einladen von Personen zu einer Hochzeit teuer ist (über 380 Pfund pro Person). Zuerst müssen Sie vorläufige Einladungen mit einem Datum und einer kurzen Benachrichtigung senden, und erst dann - vollwertig, mit einer detaillierteren Beschreibung des Ereignisses. All dies wird außerdem per Post verschickt, was bedeutet, dass es langsam ist. Versuche, die eingeladenen Personen zu „fangen“ und von ihnen eine Antwort zu erhalten, ob sie mit kostenlosem Essen und Trinken in den Urlaub kommen möchten (obwohl es den Anschein hat, wer will das nicht ?!), Nehmen viel Zeit in Anspruch. Und schließlich ist das Versenden von Einladungen nicht umweltfreundlich, da Papierkarten eine einmalige Sache sind, sie schnell vergessen und für niemanden nutzlos werden.

Aber zurück zu den Listen. Wir teilen die Gäste in mehrere Gruppen ein:

  1. Die, die Sie gerne auf dem Festival sehen würden
  2. Diejenigen, die die zweite Einladung beantworteten, baten um eine Antwort
  3. Diejenigen, die die Einladung angenommen haben
  4. Diejenigen, die die Einladung angenommen und Essen gewählt haben

Aber ich mag die Listen: Sie haben einige vordefinierte Anforderungen, die sie zu einem großartigen Objekt für die Automatisierung machen.

Flaschenpost


Ich war mir sicher, dass alle potenziellen Gäste, unabhängig von ihrem Alter, ein Mobiltelefon hatten, was bedeutete, dass die Zeit für Twilio gekommen war. Der hier angegebene Code kann auf Wunsch sicher übersprungen werden, da er immer im entsprechenden GitHub-Repository verfügbar ist.

SMS als Kommunikationskanal passte perfekt zu meinen Bedürfnissen. Ich konnte das Massenversenden von Nachrichten einrichten und die Antworten schnell und effizient verarbeiten. Als ich die ersten Arbeitsskizzen des Produkts anfertigte und die Datenbankoptionen berücksichtigte, versuchte ich, etwas Einfaches zu tun, das leicht geteilt werden konnte, und wollte nicht viel Zeit für das Erscheinungsbild aufwenden. Am Ende stieß ich auf die gspread-Python-Bibliothek, mit der ich aus Google-Tabellen lesen und in diese schreiben konnte. Dies war nicht die schnellste, sondern eine flexible Option, die den Zugriff auf Tabellen und das Lesen von Ergebnissen vereinfachte.

Für die erste Eingabeaufforderung habe ich eine Tabelle mit drei Spalten erstellt:

  • Name
  • Telefonnummer
  • Bestätigungsstatus (Bestätigungsstatus)
  • Status der Kontaktdetails
  • Message_count (Die Anzahl der an den Gast gesendeten Nachrichten hat sich in Zukunft als nützlich erwiesen.)

Nachdem ich die grundlegende Dateneingabe abgeschlossen hatte, führte ich die Liste über gspread aus , das jedem Gast, der eine Handynummer besitzt , eine SMS schickte:

import json import time import gspread from oauth2client.client import SignedJwtAssertionCredentials from twilio.rest import TwilioRestClient #      #     json,    json_key = json.load(open('.json')) scope = ['https://spreadsheets.google.com/feeds'] credentials = SignedJwtAssertionCredentials(json_key['client_email'], json_key['private_key'].encode(), scope) gc = gspread.authorize(credentials) wks = gc.open("wedding_guests") #     workbook- wks_attendees = wks.get_worksheet(0) #     ACCOUNT_SID = 'TWILIO_ACCOUNT_SID' AUTH_TOKEN = 'TWILIO_AUTH_TOKEN' client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) #    ,   range    for num in range(2, 60): print "sleeping for 2 seconds" time.sleep(2) #         guest_number = wks_attendees.acell('B'+str(num)).value guest_name = wks_attendees.acell('A'+str(num)).value Message_body = <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">"</span><span class="pl-cce">\n\n</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2709</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span><span class="pl-s"><span class="pl-pds">"</span> Save the date! <span class="pl-pds">"</span></span><span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2709</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span><span class="pl-s"><span class="pl-pds">"</span><span class="pl-cce">\n\n</span>Lauren Pang and Thomas Curtis are delighted to invite you to our wedding.<span class="pl-cce">\n\n</span>Saturday 3rd September 2016. <span class="pl-cce">\n\n</span>Colville Hall,<span class="pl-cce">\n</span>Chelmsford Road,<span class="pl-cce">\n</span>White Roding,<span class="pl-cce">\n</span>CM6 1RQ.<span class="pl-cce">\n\n</span>The Ceremony begins at 2pm.<span class="pl-cce">\n\n</span>More details will follow shortly!<span class="pl-cce">\n\n</span>Please text YES if you are saving the date and can join us or text NO if sadly, you won't be able to be with us.<span class="pl-cce">\n\n</span><span class="pl-pds">"</span></span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2B50</span><span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-k">u</span><span class="pl-pds">"</span><span class="pl-cce">\u2764</span><span class="pl-pds">"</span></span>, if not guest_number: #      print guest_name + ' telephone number empty not messaging' wks_attendees.update_acell('E'+str(num), '0') else: print 'Sending message to ' + guest_name client.messages.create( to="+" + guest_number, #  +   e.164 from_="", #     Twillio body=message_body, ) wks_attendees.update_acell('E'+str(num), int(wks_attendees.acell('E'+str(num)).value) + 1) # increment the message count row else: # else-  print 'finished' 

Und da Text-SMS normalerweise etwas langweilig aussehen, habe ich Unicode hinzugefügt, um sie aufzupeppen. So sah die Nachricht für die glücklichen Gäste aus:

Bild

Als Nächstes verwendete ich Flask als Webserver, stellte meine URL-Anfrage für Twilio Messaging auf / messages und fügte einfache if-Checks hinzu, um Antworten zu analysieren:

 @app.route("/messages", methods=['GET', 'POST']) def hello_guest():  if "yes" in body_strip:    #      confirmation_status    wks_attendees.update_acell("F"+str(guest_confirmation_cell.row), 'Accepted')  #    « »       resp.message(u"\u2665" + "Thanks for confirming, we'll be in touch!" + u"\u2665")  # r ,    elif "no" in from_body.lower():    #    « »       wks_attendees.update_acell("F"+str(guest_confirmation_cell.row), 'Declined')    #       resp.message("Sorry to hear that, we still love you though!")  else:  #  ,        resp.message("You sent a different keyword, we need a yes or a no, you sent: "+           from_body)  return str(resp) 

BildBild

Die erste Nachricht wurde am 19. Februar um 8:37 Uhr gesendet, und die erste Bestätigung ging etwas später um 8:40 Uhr ein. Um 9:38 Uhr hatte ich bereits 23 Bestätigungen erhalten, dh 32% der Antworten waren in meiner Tasche! 2 Tage nach Beginn des Massenmailing bestätigten 58% der Gäste ihre Teilnahme. Trotz des offensichtlichen Erfolgs war meine zukünftige Frau noch nicht 100% beeindruckt von meinem SMS-Service für Hochzeitseinladungen, und ich beschloss, der Anwendung weitere Funktionen hinzuzufügen.

Statistik! Ich könnte eine aktuelle Gästeliste erstellen und auf Anfrage bereitstellen, um meiner zukünftigen Braut sofort ein Feedback zu geben. Der Code erwies sich als recht einfach, da ich bereits einige der einfachsten Zähler in der Tabelle eingerichtet habe und es daher darauf ankam, den Inhalt einzelner Zellen abzurufen und zu SMS hinzuzufügen:

 #    guest_confirmed = wks_attendees.acell('C70').value guest_unconfirmed = wks_attendees.acell('C71').value guest_no_response = wks_attendees.acell('C72').value guest_acceptance = wks_attendees.acell('C73').value elif "numbers" in from_body.lower():  #   ( - ,   )  resp.message("RSVP update:\n\nTotal Accepted: " + guest_confirmed         "\n\nTotal declined: " guest_unconfirmed "\n\nTotal no response: "+         guest_no_response + "\n\nTotal acceptance rate: " + guest_acceptance) 

Beispiel für eine SMS mit diesem Code:

Bild

Es mag nicht sehr schön aussehen, aber es ist sehr informativ.

Die Tatsache, dass Lauren nun den automatischen Aktualisierungen der Gästeliste folgen konnte, ersparte uns viele Kopfschmerzen. Infolgedessen erhielt ich von ihr die Genehmigung für die weit verbreitete Integration von SMS, und bald wurde dieses Tool in fast allen Prozessen eingesetzt, in denen dies möglich war. Einige der Anwendungen waren offensichtlich, zum Beispiel das Senden von SMS-Benachrichtigungen über den Start einer Hochzeitsseite (übrigens auf Heroku erstellt ) oder das Arbeiten mit Listen von Hochzeitsgeschenken und vielen anderen Lösungen, auf die ich bis heute stolz bin.

Herrliches Fest


Nachdem die Liste der eingeladenen Personen zusammengestellt und Antworten gesammelt worden waren, kam es zu der Lektion, die normalerweise auf später verschoben wird - um die Geschmackspräferenzen der Gäste herauszufinden. Der erste Schritt bestand darin, eine weitere SMS zu senden, in der die Gäste über die Notwendigkeit informiert wurden, die Website zu besuchen und die Kategorien der Speisen auszuwählen, die über das Google-Formular serviert werden. Das Formular sah recht gewöhnlich aus, füllte jedoch dieselbe Datei, in der Daten über Besucher enthalten waren. So hatten wir jetzt sowohl einen Besuchertisch, der Einladungen annahm, als auch einen Tisch, an dem das Formular zur Lebensmittelauswahl ausgefüllt war. Wenn wir über ein gewöhnliches Automatisierungstool sprechen würden, müsste ich warten, bis die Gäste langsam ihre Gerichte auswählen. Meine Hochzeit wurde jedoch mit Unterstützung von Twillio abgehalten, und dies bedeutet, dass ich mit minimalem Aufwand eine Antwort von den Gästen erhalten konnte.

Es war notwendig, zwei Tabellen mit dem Namen der Gäste zu überprüfen und den Status der ausgewählten Gerichte nach Erhalt neuer Informationen zu aktualisieren. Dies erforderte einige zusätzliche Schnickschnack im Code, aber sobald ich damit fertig war, konnte ich das Skript so schnell wie nötig ausführen und eine SMS mit den neuesten Informationen erhalten:

 import json import time import gspread from oauth2client.client import SignedJwtAssertionCredentials from twilio.rest import TwilioRestClient #     json,    json_key = json.load(open('')) scope = ['https://spreadsheets.google.com/feeds'] credentials = SignedJwtAssertionCredentials(json_key['client_email'],                      json_key['private_key'].encode(),                      scope) gc = gspread.authorize(credentials) wks = gc.open("")  #      wks_attendees = wks.get_worksheet(0)  #   wks_food = wks.get_worksheet(1)  #    ACCOUNT_SID = 'TWILIO_ACCOUNT_SID' AUTH_TOKEN = 'TWILIO_AUTH_TOKEN' client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN) #   . -       for num in range(2, 60):  food_guest_name = wks_food.acell('B'+str(num)).value  #        if food_guest_name:    attendees_name = wks_attendees.find(val_food_guest_name).value    attendees_name_row = wks_attendees.find(val_food_guest_name).row    menu_status = wks_attendees.acell("G"+str(attendees_name_row)).value    if food_guest_name == attendees_name:      print      if menu_status == 'Y':  #   ,          print('Skipping')      else:  #    ,           print ('Food sheet name ' + food_guest_name + 'Attendees sheet name ' + attendees_name)        #            wks_attendees.update_acell("G"+str(attendees_name_row), 'Y')    else:      print('nothing found, moving on')      wks_attendees.update_acell('E'+str(num), int(wks.acell('E'+str(num)).value) + 1)  #      else:    #           client.messages.create(from_="",  #  Twillio                to="",  #                  body="Finished processing current meal listnnGuest meals confirmed" + guest_meals_confirmed + "\n\nGuest meals unconfirmed: " + guest_meals_unconfirmed) 

Nachdem ich nun eine genaue Gästeliste und eine ständig aktualisierte Liste der Gerichte hatte, war es sinnvoll, diese Statistiken über die Hauptanwendung öffentlich zugänglich zu machen. Dazu musste lediglich der Inhalt der entsprechenden Zellen zur SMS-Antwort hinzugefügt werden:

 #           elif "food" in body_strip.strip():  resp.message("Guest meals decided:" + guest_meals_confirmed + "\nGuest meals undecided: " + guest_meals_unconfirmed + "\n\nMenu breakdown:\n\n" + starter_option_1 +": " + starter_option_1_amount + "\n" + starter_option_2 +": " + starter_option_2_amount + "\n" + starter_option_3 +": " + starter_option_3_amount + "\n" + main_option_1 +": " + main_option_1_amount + "\n" + main_option_2 +": " + main_option_2_amount + "\n" + main_option_3 +": " + main_option_3_amount + "\n" + dessert_option_1 + ": " + dessert_option_1_amount + "\n" + dessert_option_2 + ": " + dessert_option_2_amount) 

Bild

Diese Maßnahme erwies sich als sehr nützlich, da das Unternehmen, das den Urlaub bedient, über unsere Fortschritte informiert war und sehr praktische Informationen von denjenigen lieferte, die ihre Wahl noch nicht getroffen hatten. Der nächste Anwärter auf Automatisierung war der Empfang von Antworten von Gästen. Dazu war es nur notwendig, die Liste durchzugehen, darin "Übertreter" zu finden, die ihre Gerichte nicht ausgewählt hatten, und ihnen Nachrichten zu senden!

 for num in range(2, 72):  #         print "sleeping for 3 seconds"  time.sleep(3)  #            wedding_guest_number = wks_attendees.acell('B'+str(num)).value  #     wedding_guest_name = wks_attendees.acell('A'+str(num)).value  #     menu_guest = wks_attendees.acell('G'+str(num)).value  if not wedding_guest_number:    print wedding_guest_name+' telephone number empty not messaging'  #   ,     .            wks_attendees.update_acell('H'+str(num), '1')  #         else:    if menu_guest == "N":  #    !      !      print 'Sending message to '+wedding_guest_name      client.messages.create(        to="+" + wedding_guest_number,        from_="",  #   Twillio        body="If you have received this message, you have not chosen your food options for Tom & Lauren's Wedding!\n\nYou can pick your choices via the website, no paper or postage required!\n\nhttp://www.yourwebsitehere.com/food"      )      wks_attendees.update_acell('H'+str(num), int(wks_attendees.acell('H'+str(num)).value) + 1)  #        else:          # else-   print 'finished' 

Bild

Der große Tag näherte sich schneller als wir uns vorstellen konnten. Wir mussten nur noch die letzte SMS senden, um die Gäste an die grundlegenden Details und die Notwendigkeit zu erinnern, sich mit einem Regenschirm zu bewaffnen, der zum Schutz vor dem typisch regnerischen britischen Sommer beiträgt:

Bild

Abschließend


Eine Hochzeit zu organisieren ist nie einfach. Es kann Ihnen jederzeit so erscheinen, als ob viele Aspekte des Ereignisses außerhalb Ihrer Kontrolle liegen. Die Automatisierung hat mir das Leben definitiv erleichtert, indem sie einen direkten Kommunikationskanal mit Gästen und unzählige Tools bereitstellte, mit denen sie ihren Antworten folgen und sie an die Notwendigkeit erinnern konnten, sich zu entscheiden und zu antworten. Sie half uns, eines der langweiligsten Dinge, die solche Ereignisse begleiten, selbst in die Hand zu nehmen, und erlaubte uns, viel Zeit freizugeben und uns auf andere wichtige Komponenten eines so wichtigen Ereignisses in unserem Leben zu konzentrieren.

Das Erstellen skalierbarer Lösungen für komplexe Aufgaben ist nie einfach, und selbst eine der endgültigen Versionen meiner Anwendung könnte die Aufgaben an bestimmten Stellen kaum bewältigen. Ursprünglich plante ich die Entwicklung einer umfassenderen Lösung mit Visualisierung des Fortschritts und der Sprachintegration, die weniger von CLI-Skripten abhängig war, aber in diesem Rennen herrschte Zeit. Im Allgemeinen bin ich zufrieden mit dem Ergebnis. Es gibt keine perfekten Kommunikationssysteme. Sie sollten immer den Kanal verwenden, der für Ihr Publikum am besten geeignet ist, sei es SMS , Sprache, Chat , Video oder Semaphor .

Wenn Sie über Hochzeitsautomatisierung sprechen möchten, senden Sie mir eine E-Mail auf Twitter .

Bild

Source: https://habr.com/ru/post/de402827/


All Articles