diff --git a/notifo.cpp b/notifo.cpp index 2ecea7d..de796e3 100644 --- a/notifo.cpp +++ b/notifo.cpp @@ -19,54 +19,191 @@ #error This module needs ZNC 0.072 or newer. #endif +#define DEBUG_HOST 0 +#define DEBUG_LOGGING 0 + class CNotifoMod : public CModule { + protected: + + // Too lazy to add CString("\r\n\") everywhere + CString crlf; + + // Host and URL to send messages to + CString notifo_host; + CString notifo_url; + + // User agent to use + CString user_agent; + + // Recipient account's username and API secret + CString notifo_username; + CString notifo_secret; + public: - MODCONSTRUCTOR(CNotifoMod) {} + + MODCONSTRUCTOR(CNotifoMod) { + crlf = "\r\n"; + +#if DEBUG_HOST + notifo_host = "notifo.leetcode.net"; + notifo_url = "/index.php"; +#else + notifo_host = "api.notifo.com"; + notifo_url = "/v1/send_notification"; +#endif + + user_agent = "ZNC To Notifo"; + + notifo_username = ""; + notifo_secret = ""; + } virtual ~CNotifoMod() {} - virtual void OnModCommand(const CString& sCommand) - { - PutModule("Sending message..."); - sendmessage("foo"); - } - protected: + + /** + * Shorthand for encoding a string for a URL. + * + * @param str String to be encoded + * @return Encoded string + */ CString urlencode(const CString& str) { return str.Escape_n(CString::EASCII, CString::EURL); } - void sendmessage(const CString& message) + /** + * Send a message to the currently-configured Notifo account. + * Requires (and assumes) that the user has already configured their + * username and API secret using the 'set' command. + * + * @param message Message to be sent to the user + */ + void send_message(const CString& message) { - CString crlf = "\r\n"; + // BASIC auth style + CString auth = notifo_username + CString(":") + notifo_secret; - CString auth = "foo:bar"; - - CString post = "to="; + // POST body parameters for the request + CString post = "to=" + urlencode(notifo_username); post += "&msg=" + urlencode(message); post += "&label=" + urlencode(CString("ZNC")); post += "&title=" + urlencode(CString("New Message")); - post += "&uri="; + post += "&uri=" + urlencode(CString("http://notifo.leetcode.net/")); - CString headers = "POST /index.php HTTP/1.1" + crlf; - headers += "Host: notifo.leetcode.net" + crlf; - headers += "Content-Type: application/x-www-form-urlencoded" + crlf; - headers += "Content-Length: " + CString(post.length()) + crlf; - headers += "User-Agent: zncnotifo" + crlf; - headers += "Authorization: Basic " + auth.Base64Encode() + crlf; - headers += crlf; - headers += post + crlf; + // Request headers and POST body + CString request = "POST " + notifo_url + " HTTP/1.1" + crlf; + request += "Host: " + notifo_host + crlf; + request += "Content-Type: application/x-www-form-urlencoded" + crlf; + request += "Content-Length: " + CString(post.length()) + crlf; + request += "User-Agent: " + user_agent + crlf; + request += "Authorization: Basic " + auth.Base64Encode_n() + crlf; + request += crlf; + request += post + crlf; + // Create the socket connection, write to it, and add it to the queue CSocket *sock = new CSocket(this); - sock->Connect("notifo.leetcode.net", 443, true); - sock->Write(headers); + sock->Connect(notifo_host, 443, true); + sock->Write(request); sock->Close(Csock::CLT_AFTERWRITE); AddSocket(sock); +#if DEBUG_LOGGING + // Log the HTTP request FILE *fh = fopen("/tmp/notifo.log", "a"); - fputs(headers.c_str(), fh); + fputs(request.c_str(), fh); fclose(fh); +#endif + } + + protected: + + bool OnLoad(const CString& args, CString& message) + { + notifo_username = GetNV("notifo_username"); + notifo_secret = GetNV("notifo_secret"); + + return true; + } + + /** + * Handle direct commands to the *notifo virtual user. + * + * @param command Command string + */ + void OnModCommand(const CString& command) + { + VCString tokens; + int token_count = command.Split(" ", tokens, false); + + CString action = tokens[0].AsLower(); + + // SET command + if (action == "set") + { + if (token_count != 3) + { + PutModule("Usage: set