Candidates message your bot with your booking code, see the interview times you have free, and book one themselves.
Uses
Google Calendar
Telegram
Let candidates book their own interview in Telegram
Whenever a candidate messages your Telegram bot with your booking code, they are shown the weekday interview times you actually have free, worked out from your Google Calendar. A reply giving the code, a date, a time, their name and their email books that slot, and the confirmation comes straight back in the chat.
You end up with a calendar event carrying the candidate's name in the title and their address as a guest, with an invitation on its way to them. Only the clock times you allow, on weekdays inside your booking window, can be booked, and a booking without a real name or a valid email address is refused. The slot is checked again at the moment of booking, so two candidates reading the same list cannot take the same time.
Every message that does not begin with your code is ignored in silence, so the bot can sit in a busy chat. Treat the code as a password and change it between roles.
incomingMessage.When a new message is received. Save it as incomingMessage.bookingCode to blank.Set bookingCode to blank.interviewTimeZone to blank.Set interviewTimeZone to blank.interviewTimes to 09:30, 11:00, 14:00, 15:30.Set interviewTimes to 09:30, 11:00, 14:00, 15:30.interviewMinutes to 30.Set interviewMinutes to 30.daysToLookAhead to 10.Set daysToLookAhead to 10.slotsToOffer to 4.Set slotsToOffer to 4.calendarId to primary.Set calendarId to primary.interviewTitle to Interview.Set interviewTitle to Interview.bookingCode and save it as codeWord.Trim bookingCode and save it as codeWord.interviewTimeZone and save it as meetingTimeZone.Trim interviewTimeZone and save it as meetingTimeZone.calendarId and save it as calendar.Trim calendarId and save it as calendar.interviewTitle and save it as eventTitle.Trim interviewTitle and save it as eventTitle.incomingMessage.chat_id and save it as chatId.Trim incomingMessage.chat_id and save it as chatId.chatId is empty or chatId is nullIf chatId is empty or chatId is nullincomingMessage.text and save it as messageText.Trim incomingMessage.text and save it as messageText.messageText is nullIf messageText is nullmessageText to blank.Change messageText to blank.messageText doesn't start with codeWord (ignoring case)If messageText doesn't start with codeWord (ignoring case)cleanTimes to an empty list.Set cleanTimes to an empty list.allowedTimes to "Set allowedTimes to
.clockTime in interviewTimes split by ,:For each clockTime in interviewTimes split by ,:clockTime and save it as oneTime.Trim clockTime and save it as oneTime.oneTime is emptyIf oneTime is emptyoneTime to the end of cleanTimes and save it as cleanTimes.Add oneTime to the end of cleanTimes and save it as cleanTimes.allowedTimes to allowedTimes@oneTimeChange allowedTimes to allowedTimes@oneTime
.cleanTimes is emptyIf cleanTimes is emptyofferedTimesText to - cleanTimes joined by "Set offeredTimesText to - cleanTimes joined by
- .workingDays to an empty list.Set workingDays to an empty list.dayOffset to 1.Set dayOffset to 1.dayOffset is less than or equal to daysToLookAhead multiplied by 1:While dayOffset is less than or equal to daysToLookAhead multiplied by 1:meetingTimeZone shifted by dayOffset days split by T and save it as day.Get the first item of today's date in meetingTimeZone shifted by dayOffset days split by T and save it as day.day is a weekendIf not day is a weekendday to the end of workingDays and save it as workingDays.Add day to the end of workingDays and save it as workingDays.dayOffset.Add 1 to dayOffset.workingDays is emptyIf workingDays is emptymessageText by | and save it as parts.Split messageText by | and save it as parts.parts is greater than or equal to 5If the length of parts is greater than or equal to 5parts[1] and save it as wantDate.Trim parts[1] and save it as wantDate.parts[2] and save it as wantTime.Trim parts[2] and save it as wantTime.parts[3] and save it as candidateName.Trim parts[3] and save it as candidateName.parts and save it as candidateEmail.Trim the last item of parts and save it as candidateEmail.candidateName is empty or candidateName is nullIf candidateName is empty or candidateName is nullchatId.Send a message to chat chatId.I need your name too. Reply in this shape:
codeWord | date | time | your name | your emailcandidateEmail is a valid email addressIf not candidateEmail is a valid email addresschatId.Send a message to chat chatId.That does not look like an email address, so I have not booked anything. Reply in this shape:
codeWord | date | time | your name | your emailworkingDays doesn't contain wantDateIf workingDays doesn't contain wantDatechatId.Send a message to chat chatId.I can only book weekdays inside the booking window, and that date is outside it. Send the code on its own to see what is free. The first day I can book is the first item of workingDays.allowedTimes doesn't contain wantTimeIf allowedTimes doesn't contain wantTimechatId.Send a message to chat chatId.That is not one of the interview times on offer. The times I can book are:
offeredTimesTextstartsAt to wantDateT@wantTime.Set startsAt to wantDateT@wantTime.startsAt shifted by interviewMinutes multiplied by 1 minutes split by . and save it as endsAt.Get the first item of startsAt shifted by interviewMinutes multiplied by 1 minutes split by . and save it as endsAt.startsAt to endsAt. Save it as availability.Check if the calendar is free from startsAt to endsAt. Save it as availability.availability.isAvailable isn't yesIf availability.isAvailable isn't yeschatId.Send a message to chat chatId.That time has just been taken, so I have not booked it. Send the code on its own and I will show you what is still free.candidateName' from startsAt to endsAt. Save it as booking.Create the event '@eventTitle - candidateName' from startsAt to endsAt. Save it as booking.
Calendar: calendar
Time zone: meetingTimeZoneBooked from Telegram.
Name given: candidateName
Email given: candidateEmailconfirmation to Booked. .Set confirmation to Booked. .confirmation to confirmationthe weekday name of wantDate wantDate at wantTime.Change confirmation to confirmationthe weekday name of wantDate wantDate at wantTime.confirmation to confirmation (meetingTimeZone), interviewMinutes multiplied by 1 as text minutes. The invitation is on its way to candidateEmail.Change confirmation to confirmation (meetingTimeZone), interviewMinutes multiplied by 1 as text minutes. The invitation is on its way to candidateEmail.chatId.Send a message to chat chatId.confirmationcandidateName starting startsAt, calendar event booking.event_id.Show in the output: Interview booked for candidateName starting startsAt, calendar event booking.event_id.openSlots to an empty list.Set openSlots to an empty list.slotCount to 0.Set slotCount to 0.day in workingDays:For each day in workingDays:slotCount is greater than or equal to slotsToOffer multiplied by 1 If slotCount is greater than or equal to slotsToOffer multiplied by 1slotTime in cleanTimes: For each slotTime in cleanTimes:slotCount is greater than or equal to slotsToOffer multiplied by 1 If slotCount is greater than or equal to slotsToOffer multiplied by 1slotStart to dayT@slotTime. Set slotStart to dayT@slotTime.slotStart shifted by interviewMinutes multiplied by 1 minutes split by . and save it as slotEnd. Get the first item of slotStart shifted by interviewMinutes multiplied by 1 minutes split by . and save it as slotEnd.slotError If a step below fails, save the error as slotErrorslotStart to slotEnd. Save it as slotCheck.Check if the calendar is free from slotStart to slotEnd. Save it as slotCheck.slotCheck.isAvailable is yesIf slotCheck.isAvailable is yesday day at slotTime to the end of openSlots and save it as openSlots.Add - the weekday name of day day at slotTime to the end of openSlots and save it as openSlots.slotCount.Add 1 to slotCount.slotStart: slotError as text.Show in the output: Could not check slotStart: slotError as text.slotCount is 0If slotCount is 0chatId.Send a message to chat chatId.Thanks for getting in touch. Nothing is free in the booking window at the moment - reply here and we will find a time by hand.offerText to:Set offerText to:Here are the interview times that are free:offerText to offerText plus openSlots joined by a new line.Change offerText to offerText plus openSlots joined by a new line.offerText to offerTextChange offerText to offerText
To book one, reply in exactly this shape:
codeWord | date | time | your name | your email
For example:
.offerText to offerText@codeWord | the first item of workingDays | the first item of cleanTimes | Alex Green | alex@example.com.Change offerText to offerText@codeWord | the first item of workingDays | the first item of cleanTimes | Alex Green | alex@example.com.chatId.Send a message to chat chatId.offerText