Microblog (#18)
* Microblog Plugin Display information about new blog entry
This commit is contained in:
191
development/microblog.c
Normal file
191
development/microblog.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Stefan Kropp <stefan@debxwoody.de>
|
||||
*
|
||||
* This file is part of profanity.
|
||||
*
|
||||
* profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!! Status: Development / Testing !!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
*
|
||||
* File: microblog.c
|
||||
*
|
||||
* The microblog plugin can be used for Movim Users. If profanity gets a message
|
||||
* "urn:xmpp:microblog:0", it will display the from, title and ID information of
|
||||
* the blog post.
|
||||
*
|
||||
* Profanity will display a message like this, in the main Window:
|
||||
*
|
||||
* Blog from user@domain.tld - Title of the post (ID of the post)
|
||||
*
|
||||
* Compile:
|
||||
*
|
||||
* gcc -shared -fpic -g3 -O0 -Wextra -pedantic \
|
||||
* -L/usr/lib/profanity -lprofanity `pkg-config --libs --cflags libxml-2.0` \
|
||||
* -o microblog.so microblog.c
|
||||
*
|
||||
* Install:
|
||||
*
|
||||
* cp microblog.so \
|
||||
* ~/.local/share/profanity/plugins/
|
||||
*
|
||||
* Documentation:
|
||||
*
|
||||
* https://profanity-im.github.io/plugins.html
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <profapi.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PLUGIN_NAME "microblog"
|
||||
#define PLUGIN_VERSION "0.0.1-DEV"
|
||||
|
||||
#define XMPP_URN_MICROBLOG "urn:xmpp:microblog:0"
|
||||
|
||||
/**
|
||||
* PubSubEvent is the struct with all data of the stanza, which should be
|
||||
* displayed or processed by the plugin..
|
||||
*/
|
||||
typedef struct {
|
||||
char *id; // id of the item
|
||||
char *from; // jid from
|
||||
char *title; // title of the item
|
||||
} PubSubEvent;
|
||||
|
||||
// Enable or disable Plugin
|
||||
|
||||
static bool enabled = true;
|
||||
|
||||
/**
|
||||
* Parse the char* stanza and return the information in event.
|
||||
* The function will return true on success, otherwise false.
|
||||
*/
|
||||
bool parse(const char *stanza, PubSubEvent *event) {
|
||||
bool result = false;
|
||||
// stanza and event are mandatory
|
||||
if (stanza == NULL || event == NULL || strlen(stanza) == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
xmlDocPtr doc;
|
||||
xmlNode *root_element = NULL;
|
||||
|
||||
doc = xmlReadMemory(stanza, strlen(stanza), NULL, NULL, 0);
|
||||
if (doc == NULL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
|
||||
xmlXPathRegisterNs(xpathCtx, BAD_CAST "ev",
|
||||
BAD_CAST "http://jabber.org/protocol/pubsub#event");
|
||||
xmlXPathRegisterNs(xpathCtx, BAD_CAST "a",
|
||||
BAD_CAST "http://www.w3.org/2005/Atom");
|
||||
|
||||
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(
|
||||
"//message/ev:event/ev:items/attribute::node", xpathCtx);
|
||||
|
||||
if (xpathObj != NULL && xpathObj->nodesetval != NULL &&
|
||||
xpathObj->nodesetval->nodeTab[0] != NULL) {
|
||||
if (xpathObj->nodesetval->nodeTab[0]->children != NULL &&
|
||||
xpathObj->nodesetval->nodeTab[0]->children->content != NULL) {
|
||||
if (strcmp(xpathObj->nodesetval->nodeTab[0]->children->content,
|
||||
XMPP_URN_MICROBLOG) == 0) {
|
||||
xpathObj =
|
||||
xmlXPathEvalExpression("//message/attribute::from", xpathCtx);
|
||||
assert(xpathObj != NULL);
|
||||
|
||||
event->from =
|
||||
strdup(xpathObj->nodesetval->nodeTab[0]->children->content);
|
||||
xmlXPathFreeObject(xpathObj);
|
||||
|
||||
xpathObj = xmlXPathEvalExpression(
|
||||
"//message/ev:event/ev:items/ev:item/a:entry/a:title", xpathCtx);
|
||||
assert(xpathObj != NULL);
|
||||
|
||||
event->title =
|
||||
strdup(xpathObj->nodesetval->nodeTab[0]->children->content);
|
||||
xmlXPathFreeObject(xpathObj);
|
||||
|
||||
xpathObj = xmlXPathEvalExpression(
|
||||
"//message/ev:event/ev:items/ev:item/attribute::id", xpathCtx);
|
||||
assert(xpathObj != NULL);
|
||||
|
||||
event->id = strdup(xpathObj->nodesetval->nodeTab[0]->children->content);
|
||||
xmlXPathFreeObject(xpathObj);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xpathCtx) {
|
||||
xmlXPathFreeContext(xpathCtx);
|
||||
}
|
||||
if (doc) {
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void prof_init(const char *const version, const char *const status,
|
||||
const char *const account_name, const char *const fulljid) {
|
||||
char *s = NULL;
|
||||
asprintf(&s, "Loaded Plugin %s %s", PLUGIN_NAME, PLUGIN_VERSION);
|
||||
prof_cons_show(s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
void prof_on_start(void) {}
|
||||
|
||||
void prof_on_shutdown(void) {}
|
||||
|
||||
void prof_on_unload(void) {
|
||||
char *s = NULL;
|
||||
asprintf(&s, "Unloading Plugin %s %s", PLUGIN_NAME, PLUGIN_VERSION);
|
||||
prof_cons_show(s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
int prof_on_message_stanza_receive(const char *const stanza) {
|
||||
if (enabled) {
|
||||
PubSubEvent event;
|
||||
event.id = NULL;
|
||||
event.from = NULL;
|
||||
event.title = NULL;
|
||||
if (parse(stanza, &event)) {
|
||||
int size =
|
||||
strlen(event.id) + strlen(event.from) + strlen(event.title) + 30;
|
||||
char *message = calloc(size, sizeof(char));
|
||||
snprintf(message, size, "Blog from %s - %s (%s)", event.from, event.title,
|
||||
event.id);
|
||||
prof_cons_show(message);
|
||||
prof_cons_alert();
|
||||
free(message);
|
||||
free(event.id);
|
||||
free(event.from);
|
||||
free(event.title);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user