Last active
          October 20, 2025 00:44 
        
      - 
      
- 
        Save hcgatewood/02f18e736093e7d308dcbebd383bcc27 to your computer and use it in GitHub Desktop. 
    Automated apartment complex buzzer entry
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | // DIY version of e.g. https://lowkeybuzzer.com | |
| const axios = require("axios"); | |
| exports.handler = async function(context, event, callback) { | |
| const twiml = new Twilio.twiml.VoiceResponse(); | |
| const logWebhookUrl = context.DISCORD_WEBHOOK_LOGS || ""; | |
| const doGrantAccess = ["", "true", "1", "yes"].includes((context.DO_GRANT_ACCESS || "").toLowerCase()); // default true | |
| const doForward = ["", "true", "1", "yes"].includes((context.DO_FORWARD_CALLS || "").toLowerCase()); // default true | |
| const buzzerNumber = context.BUZZER_PHONE_NUMBER || ""; | |
| const forwardNumber = context.PERSONAL_PHONE_NUMBER || ""; | |
| if (buzzerNumber === "") { | |
| console.warn("BUZZER_PHONE_NUMBER environment variable is not set"); | |
| } | |
| if (forwardNumber === "") { | |
| console.warn("PERSONAL_PHONE_NUMBER environment variable is not set"); | |
| } | |
| const digitsAccept = context.DIGITS_ACCEPT || "9"; | |
| const digitsAcceptExtra = context.DIGITS_ACCEPT_EXTRA || ""; | |
| const pauseSecsBefore = Number(context.PAUSE_SECONDS_BEFORE) || 7; | |
| const pauseSecsExtraBefore = Number(context.PAUSE_SECONDS_EXTRA_BEFORE) || 3; | |
| const pauseSecsAfter = Number(context.PAUSE_SECONDS_AFTER) || 3; | |
| const log = async (msg) => { | |
| console.log(msg); | |
| if (logWebhookUrl === "") { | |
| return; | |
| } | |
| try { | |
| await axios.post(logWebhookUrl, { content: msg }); | |
| } catch (err) { | |
| console.error(`Error sending log to Discord: ${err}`); | |
| } | |
| }; | |
| // Handle buzzer call | |
| if (event.From === buzzerNumber) { | |
| // Grant access | |
| if (doGrantAccess) { | |
| await log(`Receiving call from ${event.From}. Detected as buzzer call. Granting access.`); | |
| twiml.pause({ length: pauseSecsBefore }); | |
| twiml.play({ digits: digitsAccept }); | |
| if (digitsAcceptExtra !== "") { | |
| twiml.pause({ length: pauseSecsExtraBefore }); | |
| twiml.play({ digits: digitsAcceptExtra }); | |
| } | |
| } else { | |
| await log(`Receiving call from ${event.From}. Detected as buzzer call. Denying access.`); | |
| } | |
| twiml.pause({ length: pauseSecsAfter }); | |
| } else { | |
| // Forward everything else, e.g. for phone number verification | |
| if (!doForward) { | |
| await log(`Receiving call from ${event.From}. Detected as normal call. Won't forward since call forwarding is disabled.`); | |
| } else if (forwardNumber === "") { | |
| await log(`Receiving call from ${event.From}. Detected as normal call. Won't forward since forward number not configured.`); | |
| } else { | |
| await log(`Receiving call from ${event.From}. Detected as normal call. Forwarding to ${forwardNumber}.`); | |
| twiml.dial(forwardNumber); | |
| } | |
| } | |
| callback(null, twiml); | |
| }; | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | const axios = require("axios"); | |
| exports.handler = async function(context, event, callback) { | |
| // NOTE: requires the "axios" NPM package added to the Twilio Service's dependencies | |
| // NOTE: proactive SMS messaging requires registering as a sole proprietor | |
| // REF: https://www.twilio.com/docs/messaging/compliance/a2p-10dlc/direct-sole-proprietor-registration-overview | |
| // REF: https://console.twilio.com/us1/develop/sms/regulatory-compliance/a2p-10dlc-overview | |
| const twiml = new Twilio.twiml.MessagingResponse(); | |
| const logWebhookUrl = context.DISCORD_WEBHOOK_LOGS || ""; | |
| const doForwardSMS = ["", "true", "1", "yes"].includes((context.DO_FORWARD_SMS || "").toLowerCase()); // default true | |
| const doForwardDiscord = ["", "true", "1", "yes"].includes((context.DO_FORWARD_DISCORD || "").toLowerCase()); // default true | |
| const forwardSMSNumber = doForwardSMS ? (context.PERSONAL_PHONE_NUMBER || "") : ""; | |
| const forwardDiscordURL = doForwardDiscord ? (context.DISCORD_WEBHOOK_SMS || "") : ""; | |
| const doForward = (forwardSMSNumber !== "") || (forwardDiscordURL !== ""); | |
| const log = async (msg) => { | |
| console.log(msg); | |
| if (logWebhookUrl === "") { | |
| return; | |
| } | |
| try { | |
| await axios.post(logWebhookUrl, { content: msg }); | |
| } catch (err) { | |
| console.error(`Error sending log to Discord: ${err}`); | |
| } | |
| }; | |
| // Forward everything, e.g. for phone number verification | |
| if (!doForward) { | |
| await log(`Receiving SMS from ${event.From}. Won't forward since no forward configured.`); | |
| } | |
| if (forwardSMSNumber !== "") { | |
| await log(`Receiving SMS from ${event.From}. Forwarding via SMS to ${forwardSMSNumber}.`); | |
| const msg = `New text from ${event.From}:\n\n${event.Body}`; | |
| twiml.message({ to: forwardSMSNumber }, msg); | |
| } | |
| if (forwardDiscordURL !== "") { | |
| await log(`Receiving SMS from ${event.From}. Forwarding via Discord to configured SMS webhook.`); | |
| const msg = `New text from **${event.From}**\n>>> ${event.Body}` | |
| try { | |
| await axios.post(forwardDiscordURL, { content: msg }); | |
| } catch (err) { | |
| console.error(`Error forwarding SMS to Discord: ${err}`); | |
| } | |
| } | |
| callback(null, twiml); | |
| }; | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment