2011-01-11 03:33:13 +00:00
|
|
|
/**
|
|
|
|
* ZNC Notifo Module
|
|
|
|
*
|
|
|
|
* Allows the user to enter a Notifo user and API token, and sends
|
|
|
|
* channel highlights and personal messages to Notifo.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2011 John Reese
|
|
|
|
* Licensed under the MIT license
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define REQUIRESSL
|
|
|
|
|
|
|
|
#include "znc.h"
|
|
|
|
#include "Chan.h"
|
|
|
|
#include "User.h"
|
|
|
|
#include "Modules.h"
|
|
|
|
|
|
|
|
#if (!defined(VERSION_MAJOR) || !defined(VERSION_MINOR) || (VERSION_MAJOR == 0 && VERSION_MINOR < 72))
|
|
|
|
#error This module needs ZNC 0.072 or newer.
|
|
|
|
#endif
|
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
#define DEBUG_HOST 0
|
|
|
|
#define DEBUG_LOGGING 0
|
|
|
|
|
2011-01-11 03:33:13 +00:00
|
|
|
class CNotifoMod : public CModule
|
|
|
|
{
|
2011-01-13 21:26:31 +00:00
|
|
|
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;
|
|
|
|
|
2011-01-11 03:33:13 +00:00
|
|
|
public:
|
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
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 = "";
|
2011-01-11 03:33:13 +00:00
|
|
|
}
|
2011-01-13 21:26:31 +00:00
|
|
|
virtual ~CNotifoMod() {}
|
2011-01-11 03:33:13 +00:00
|
|
|
|
|
|
|
protected:
|
2011-01-13 21:26:31 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Shorthand for encoding a string for a URL.
|
|
|
|
*
|
|
|
|
* @param str String to be encoded
|
|
|
|
* @return Encoded string
|
|
|
|
*/
|
2011-01-11 03:33:13 +00:00
|
|
|
CString urlencode(const CString& str)
|
|
|
|
{
|
|
|
|
return str.Escape_n(CString::EASCII, CString::EURL);
|
|
|
|
}
|
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
2011-01-11 03:33:13 +00:00
|
|
|
{
|
2011-01-13 21:26:31 +00:00
|
|
|
// BASIC auth style
|
|
|
|
CString auth = notifo_username + CString(":") + notifo_secret;
|
2011-01-11 03:33:13 +00:00
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
// POST body parameters for the request
|
|
|
|
CString post = "to=" + urlencode(notifo_username);
|
2011-01-11 03:33:13 +00:00
|
|
|
post += "&msg=" + urlencode(message);
|
|
|
|
post += "&label=" + urlencode(CString("ZNC"));
|
|
|
|
post += "&title=" + urlencode(CString("New Message"));
|
2011-01-13 21:26:31 +00:00
|
|
|
post += "&uri=" + urlencode(CString("http://notifo.leetcode.net/"));
|
2011-01-11 03:33:13 +00:00
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
// 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;
|
2011-01-11 03:33:13 +00:00
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
// Create the socket connection, write to it, and add it to the queue
|
2011-01-11 03:33:13 +00:00
|
|
|
CSocket *sock = new CSocket(this);
|
2011-01-13 21:26:31 +00:00
|
|
|
sock->Connect(notifo_host, 443, true);
|
|
|
|
sock->Write(request);
|
2011-01-11 03:33:13 +00:00
|
|
|
sock->Close(Csock::CLT_AFTERWRITE);
|
|
|
|
AddSocket(sock);
|
|
|
|
|
2011-01-13 21:26:31 +00:00
|
|
|
#if DEBUG_LOGGING
|
|
|
|
// Log the HTTP request
|
2011-01-11 03:33:13 +00:00
|
|
|
FILE *fh = fopen("/tmp/notifo.log", "a");
|
2011-01-13 21:26:31 +00:00
|
|
|
fputs(request.c_str(), fh);
|
2011-01-11 03:33:13 +00:00
|
|
|
fclose(fh);
|
2011-01-13 21:26:31 +00:00
|
|
|
#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 <option> <value>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CString option = tokens[1].AsLower();
|
|
|
|
CString value = tokens[2];
|
|
|
|
|
|
|
|
if (option == "username")
|
|
|
|
{
|
|
|
|
SetNV("notifo_username", value);
|
|
|
|
notifo_username = value;
|
|
|
|
}
|
|
|
|
else if (option == "secret")
|
|
|
|
{
|
|
|
|
SetNV("notifo_secret", value);
|
|
|
|
notifo_secret = value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PutModule("Error: invalid option name");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PutModule("Done");
|
|
|
|
}
|
|
|
|
// GET command
|
|
|
|
else if (action == "get")
|
|
|
|
{
|
|
|
|
if (token_count != 2)
|
|
|
|
{
|
|
|
|
PutModule("Usage: get <option>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CString option = tokens[1].AsLower();
|
|
|
|
|
|
|
|
if (option == "username")
|
|
|
|
{
|
|
|
|
PutModule(GetNV("notifo_username"));
|
|
|
|
}
|
|
|
|
else if (option == "secret")
|
|
|
|
{
|
|
|
|
PutModule(GetNV("notifo_secret"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PutModule("Error: invalid option name");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// SEND command
|
|
|
|
else if (action == "send")
|
|
|
|
{
|
|
|
|
CString message = command.Token(1, true, " ", true);
|
|
|
|
send_message(message);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PutModule("Error: invalid command");
|
|
|
|
}
|
2011-01-11 03:33:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULEDEFS(CNotifoMod, "Send highlights and personal messages to a Notifo account")
|