外國大佬和她的愛人利用Python和Google「自動化」婚禮?服氣!

外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!

2016年9月3日,對世界上的大多數人而言可能只是尋常無奇的一天,但對我而言,將永生難忘,因為在那一天我和我的愛人結婚了。

(私信小編007即可自動獲取大量python視頻教程以及各類PDF!)

在規劃婚禮時,要考慮許多不同的方面。食物、裝飾、桌子裝置(是的,這是獨立於裝飾的一個重要環節)、鮮花、住宿、交通、娛樂和位置選擇等。雖然在規劃婚禮時有許多未知數,但是我可以肯定一件事。在婚禮中,將會有很多的邀請名單、嵌套名單、以及其他更多相關名單等等。當我面對著越來越多的項目時,我開始懷疑是否有更好的方法來進行處理?如果一切都只是依賴手動,實在是太低效了,必須利用一些技術來進行改進。

你可能會感到驚訝,但是邀請人們參加婚禮是昂貴的(超過380磅),因為你需要發送“按時出席”卡片以及隨後的關於婚禮細節的邀請。這個過程也是很慢的,因為你必須通過郵寄的方式來進行發送。追蹤人們是否已經收到了邀請,以及他們是否想要參加提供免費食物和飲料的派對。最後,邀請卡也並不環保,因為它們都是被一次性使用,且容易丟失或放錯。

回到名單問題。嘉賓名單分為幾個部分:

1、你想要邀請的人的名單;

2、已經回覆你的R.S.V.P邀請函的人的名單;

3、已經回覆你會來的人的名單;

4、已經回覆你會來且選擇參加提供免費食物和飲料派對的人的名單;

注:R.S.V.P. 是法語短語“répondez,s’il vous pla?t”的縮寫,英文意思大概等於Will youplease reply 漢語翻譯成請儘快回答或請馬上回答。“R.S.V.P.”的作用就是在於禮貌地提醒人們一個他們應該早就知道的道理:如果您收到請柬,就應該回復。

名單是好的,它們具有預定義的要求和響應,這使其成為自動化的重要選擇。

瓶中信(Message In a Bottle)

不管處於何種年齡層,我確信婚禮名單上每個人都有手機,這意味著該是Twilio(一個做成開放插件的電話跟蹤服務)發揮作用的時候了。如果你想要查看代碼信息,你可以看看GitHub上的repo。

https://github.com/SeekTom/Twilio/tree/master/Wedication 

外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!

SMS完美的滿足了我的需求。我可以配置發出群發短信,並快速有效地處理回應。在繪製一個MVP並且考慮數據庫的時候,我想要一些易於分享的東西,不想浪費時間來構建視圖。偶然發現的gspread python庫,使我能夠讀寫谷歌電子表格。雖然不是最快的選擇,但它確實足夠靈活,並提供了一個易於訪問和可讀的輸出。

對於初始的R.S.V.P,我創建了一個包含以下信息的電子表格:

Name(名字);

Telephone_number(電話號碼);

Confirmation_status(確認狀態);

Contact detail status(聯繫的具體狀態)

Message_count (發送給客人的郵件數量,稍後會派上用場)

主要數據輸入完成後,我使用gspread來遍歷列表,並向每一個具有與之相關聯的手機號碼的客人發送短信:Sheets.py

import json
import time
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
from twilio.rest import TwilioRestClient
# Message your attendees from a spreadsheet
# add file name for the json created for the spreadsheet
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") # add your workbook name here
wks_attendees = wks.get_worksheet(0) # attendees worksheet
ACCOUNT_SID = 'TWILIO_ACCOUNT_SID'
AUTH_TOKEN = 'TWILIO_AUTH_TOKEN'
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
# to iterate between guests, amend this based on your total
for num in range(2, 60):
print "sleeping for 2 seconds"
time.sleep(2) # adding a delay to avoid filtering
guest_number = wks_attendees.acell('B'+str(num)).value
guest_name = wks_attendees.acell('A'+str(num)).value
Message_body = u"\\u2B50" + u"\\u2764" + u"\\u2B50"
+ u"\\u2764" + u"\\u2B50" + u"\\u2764" + u"\\u2B50" +
u"\\u2764" + "\n\n" + u"\\u2709" +" Save the date! "+ u"\\u2709
"
+"\n\nLauren Pang and Thomas Curtis are delighted to invite you to our wedding.\n\nSaturday 3rd September 2016. \n\nColville Hall,\nChelmsford Road,\nWhite Roding,\nCM6 1RQ.\n\nThe Ceremony begins at 2pm.\n\nMore details will follow shortly!\n\nPlease 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.\n\n" u"\\u2B50" + u"\\u2764
"
+ u"\\u2B50" + u"\\u2764" + u"\\u2B50" + u"\\u2764"
+ u"\\u2B50" + u"\\u2764",
if not guest_number: # No mobile number skip this guest
print guest_name + ' telephone number empty not messaging'
wks_attendees.update_acell('E'+str(num), '0') # set number to 0
else:
print 'Sending message to ' + guest_name
client.messages.create(
to="+" + guest_number, # add the + back to make the number e.164
from_="", # your twilio number here
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 part of the loop
print 'finished'

因為短信可以看起來很簡單,所以我添加了一些unicode來增加趣味。下面是幸運的受邀者接收到的短信模版:

外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


接下來,我使用Flask作為我的web服務器,並將我的Twilio消息請求URL指向/messages url並創建簡單的if語句來解析回覆 (yes,,no):hello_guest.py

@app.route("/messages", methods=['GET', 'POST'])
def hello_guest():
if "yes" in body_strip:
# We have a keeper! Find the attendee and update their confirmation_status
wks_attendees.update_acell("F"+str(guest_confirmation_cell.row), 'Accepted') # update the status to accepted for that guest
resp.message(u"\\u2665" + "Thanks for confirming, we'll be in touch!" + u"\\u2665") # respond to the guest with a confirmation!
elif "no" in from_body.lower():
# update the confirmation_status row to declined for that guest
wks_attendees.update_acell("F"+str(guest_confirmation_cell.row), 'Declined')
# respond to the user confirming the action
resp.message("Sorry to hear that, we still love you though!")
else: # respond with invalid keyword
resp.message("You sent a different keyword, we need a yes or a no, you sent: "+
from_body)
return str(resp)


外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


第一條消息是在2月19日上午8:37的時候發出的,3分鐘後(即上午8:40)收到了第一條確認短信。上午9:38,我已經收到了23條確認回覆,已經達到32%的接受率!初始群發短信兩天後,我們收到了58%的客人的確認信息!儘管取得了明顯的成功,但我的未婚妻並不完全青睞我作為婚禮邀請服務(SAAWIS?)的短信,所以,我決定在我的應用程序中添加一些其他功能。

這個功能就是統計!我可以計算現場出席名單並按要求退回,給予新娘關於客戶名單是如何塑造的即時反饋。代碼很簡單,因為我已經在電子表格中設置了一些基本的計數器,因此剩下的只是抓取這些單元格的內容,並將其添加到短信中的事情:hello_guest.py

# attendance variables
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():
# return statistics (total guests, food choices list)
resp.message("R.S.V.P update:\n\nTotal Accepted: " + guest_confirmed
"\n\nTotal declined: " guest_unconfirmed "\n\nTotal no response: "+
guest_no_response + "\n\nTotal acceptance rate: " + guest_acceptance)

以下是最終的短信,不是很漂亮,但很有用:


外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


現在Lauren可以即時跟蹤出席率的情況,這大大緩解了她的壓力。從那時起,所有的事情都通過系統來運作,SMS被儘可能多的融入到婚禮的方方面面。有些是顯而易見的,例如當婚禮網站上線時,發送通知短信,分享禮物列表以及其他我至今仍然感到驕傲的事情。

食物環節

在建立R.S.V.P名單之後,經常被推遲的部分是讓客人確認他們的食物選擇。你可能會驚訝,讓人們選擇免費的食物是能有多困難。第一步是發送另一條短信,告訴那些確認參加婚禮的客人訪問網站,並通過一個谷歌表單選擇他們喜歡的食物。相當標準的流程,然而,表單被設置為填充與參與者相同的工作簿。這意味著,我現在已經有接受邀請客人的電子表格,以及那些填寫了食物選擇表格的客人名單。通常我會等待客人慢慢選擇他們的飯菜,但因為我的婚禮是由Twilio驅動的,也就意味著我可以用最少的努力來跟蹤嘉賓狀態。

數據需要匹配訪客名稱上的兩個電子表格,並且在有匹配的時候更新客人的食物選擇狀態。這需要一些額外的工作,但一旦重排代碼,我就可以按需批量運行腳本,並通過短信獲取我的客人的最新狀態:food.py

import json
import time
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
from twilio.rest import TwilioRestClient
# add file name for the json created for the spread sheet
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("") # add your spreadsheet name here
wks_attendees = wks.get_worksheet(0) # attendees worksheet
wks_food = wks.get_worksheet(1) # food responses worksheet
ACCOUNT_SID = 'TWILIO_ACCOUNT_SID'
AUTH_TOKEN = 'TWILIO_AUTH_TOKEN'
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
# to iterate between 10 to 60 manual hack to ensure no guests not left out
for num in range(2, 60):
food_guest_name = wks_food.acell('B'+str(num)).value # food choice name column
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': # data already matched, move on
print('Skipping')
else: # user has supplied their choices, update main spreadsheet
print ('Food sheet name ' + food_guest_name + 'Attendees sheet name ' + attendees_name)
# update menu choices row
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) # increment the message count row
else:
# send message to the admin that the process has been completed with update stats
client.messages.create(from_="", # twilio number here
to="", # admin number here
body="Finished processing current meal listnnGuest meals confirmed" + guest_meals_confirmed + "\n\nGuest meals unconfirmed: " + guest_meals_unconfirmed)

現在有一個確認的客人名單和越來越多的食物選擇名單,通過主要應用程序將這些統計數據公開是有意義的。所有需要做的就是抓取相關單元格的內容,並用短信回覆:Hello_guest.py

# respond with the current food totals and the meal choices
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)


外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


讓婚禮餐飲者瞭解我們的進展,並提供有關誰沒有選擇的可操作數據是非常方便的。追蹤客人是另一個自動化選擇。簡單地遍歷參加者名單,找到沒有選擇用餐選項的頑皮客人,並向其發送信息!Chase.py

for num in range(2, 72): # manual hack to ensure no guests not left out
print "sleeping for 3 seconds"
time.sleep(3) # adding a delay to avoid carrier filtering
wedding_guest_number = wks_attendees.acell('B'+str(num)).value # grab attendee tel number
wedding_guest_name = wks_attendees.acell('A'+str(num)).value # grab attendee name
menu_guest = wks_attendees.acell('G'+str(num)).value
if not wedding_guest_number:
print wedding_guest_name+' telephone number empty not messaging' # output to console that we are not messaging this guest due to lack of telephone number
wks_attendees.update_acell('H'+str(num), '1') # increment the message count row for the individual user
else:
if menu_guest == "N": # guest has not chosen food! CHASE THEM!
print 'Sending message to '+wedding_guest_name
client.messages.create(
to="+" + wedding_guest_number,
from_="", # your Twilio number here
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) # increment the message count row for the individual user
else: # else part of the loop
print 'finished'

外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


大婚的日子來得比我們想象的還要快。現在唯一需要做的事就是發送最後一條短信,提醒客人基本的細節,並提醒他們帶把傘以防碰上一般的英國夏季的雨季:


外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!


總結

婚禮永遠不是一件簡單的事情,它會讓你感到很多事情都不在你掌控之中。自動化讓我的生活變得更加輕鬆,它可以提供與我們的客人進行溝通的直接渠道,而且我通過各種不同的方式來跟蹤、推動以及回應客人。它幫助我們在婚禮的時間消耗方面變得積極主動,讓我們可以空出來時間去關注大日子的其他重要領域。

外國大佬和她的愛人利用Python和Google“自動化”婚禮?服氣!

構建複雜問題的可擴展解決方案從來都不是件容易的事,即使在最終形式下,我的應用程序有時也會很脆弱。我已經計劃建立一個更為完整的解決方案,具有進度的數據可視化、語音集成,以及更少的依賴CLI腳本等。總的來說,我很滿意整個自動化的過程,沒有通訊系統是完美的。你需要實施最適合你的受眾的渠道,無論是短信、語音、聊天、視頻還是信號量等。


分享到:


相關文章: