roster fetch and smart oob-ing

master
bqv 2 years ago
parent 40af811d42
commit 04a152cc1f
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

9
.gitignore vendored

@ -53,3 +53,12 @@ cscope*
# Symbolic links
mdb.c
# Generated
sexp/lexer.yy.cc
sexp/location.hh
sexp/parser.output
sexp/parser.tab.cc
sexp/parser.tab.hh
sexp/position.hh
sexp/stack.hh

@ -8,6 +8,7 @@
#include <stdio.h>
#include <time.h>
#include <regex>
#include <fmt/core.h>
#include <strophe.h>
#include <weechat/weechat-plugin.h>
@ -1051,6 +1052,77 @@ struct t_channel_member *channel__remove_member(struct t_account *account,
return member;
}
int channel__send_message(struct t_account *account, struct t_channel *channel,
std::string to, std::string body,
std::optional<std::string> oob = {})
{
xmpp_stanza_t *message = xmpp_message_new(account->context,
channel->type == CHANNEL_TYPE_MUC
? "groupchat" : "chat",
to.data(), NULL);
char *id = xmpp_uuid_gen(account->context);
xmpp_stanza_set_id(message, id);
xmpp_free(account->context, id);
xmpp_message_set_body(message, body.data());
if (oob)
{
xmpp_stanza_t *message__x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__x, "x");
xmpp_stanza_set_ns(message__x, "jabber:x:oob");
xmpp_stanza_t *message__x__url = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__x__url, "url");
xmpp_stanza_t *message__x__url__text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(message__x__url__text, oob->data());
xmpp_stanza_add_child(message__x__url, message__x__url__text);
xmpp_stanza_release(message__x__url__text);
xmpp_stanza_add_child(message__x, message__x__url);
xmpp_stanza_release(message__x__url);
xmpp_stanza_add_child(message, message__x);
xmpp_stanza_release(message__x);
}
xmpp_stanza_t *message__active = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__active, "active");
xmpp_stanza_set_ns(message__active, "http://jabber.org/protocol/chatstates");
xmpp_stanza_add_child(message, message__active);
xmpp_stanza_release(message__active);
xmpp_stanza_t *message__request = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__request, "request");
xmpp_stanza_set_ns(message__request, "urn:xmpp:receipts");
xmpp_stanza_add_child(message, message__request);
xmpp_stanza_release(message__request);
xmpp_stanza_t *message__markable = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__markable, "markable");
xmpp_stanza_set_ns(message__markable, "urn:xmpp:chat-markers:0");
xmpp_stanza_add_child(message, message__markable);
xmpp_stanza_release(message__markable);
xmpp_stanza_t *message__store = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__store, "store");
xmpp_stanza_set_ns(message__store, "urn:xmpp:hints");
xmpp_stanza_add_child(message, message__store);
xmpp_stanza_release(message__store);
xmpp_send(account->connection, message);
xmpp_stanza_release(message);
if (channel->type != CHANNEL_TYPE_MUC)
weechat_printf_date_tags(channel->buffer, 0,
"xmpp_message,message,private,notify_none,self_msg,log1",
"%s\t%s",
user__as_prefix_raw(account, account_jid(account)),
body);
return WEECHAT_RC_OK;
}
int channel__send_message(struct t_account *account, struct t_channel *channel,
const char *to, const char *body)
{
@ -1145,40 +1217,68 @@ int channel__send_message(struct t_account *account, struct t_channel *channel,
{
std::string url { &*match[0].first, static_cast<size_t>(match[0].length()) };
//struct t_hashtable *options = weechat_hashtable_new (8,
// WEECHAT_HASHTABLE_STRING,
// WEECHAT_HASHTABLE_STRING,
// NULL,
// NULL);
//if (!options) { return; }
//weechat_hashtable_set(options, "nobody", "1");
//auto command = "url:" + url;
//const int timeout = 30000;
//struct t_hook *process_hook =
// weechat_hook_process_hashtable(command, options, timeout,
// int (*callback)(const void *pointer, void *data,
// const char *command,
// int return_code, const char *out, const char *err),
// const void *callback_pointer, void *callback_data);
//weechat_hashtable_free(options);
xmpp_stanza_t *message__x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__x, "x");
xmpp_stanza_set_ns(message__x, "jabber:x:oob");
xmpp_stanza_t *message__x__url = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__x__url, "url");
xmpp_stanza_t *message__x__url__text = xmpp_stanza_new(account->context);
xmpp_stanza_set_text(message__x__url__text, url.data());
xmpp_stanza_add_child(message__x__url, message__x__url__text);
xmpp_stanza_release(message__x__url__text);
xmpp_stanza_add_child(message__x, message__x__url);
xmpp_stanza_release(message__x__url);
do {
struct t_hashtable *options = weechat_hashtable_new(8,
WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING,
NULL, NULL);
if (!options) { return WEECHAT_RC_ERROR; };
weechat_hashtable_set(options, "header", "1");
weechat_hashtable_set(options, "nobody", "1");
auto command = "url:" + url;
const int timeout = 30000;
struct message_task {
struct t_account *account;
struct t_channel *channel;
std::string to;
std::string body;
std::string url;
};
auto *task = new message_task { account, channel, to, body, url };
auto callback = [](const void *pointer, void *,
const char *, int ret, const char *out, const char *err) {
auto task = static_cast<const message_task*>(pointer);
if (!task) return WEECHAT_RC_ERROR;
if (ret == 0)
{
const std::string_view prefix = "content-type: ";
std::istringstream ss(out ? out : "");
std::string line;
while (std::getline(ss, line)) {
std::transform(line.begin(), line.end(), line.begin(),
[](char c) -> char { return std::tolower(c); });
if (line.starts_with(prefix)) break;
}
std::string mime = line.substr(prefix.size());
if (mime.starts_with("image") || mime.starts_with("video"))
{
weechat_printf_date_tags(task->channel->buffer, 0,
"notify_none,no_log", "[oob]\t%s%s",
weechat_color("gray"), mime.data());
channel__send_message(task->account, task->channel,
task->to, task->body, { task->url });
}
else
channel__send_message(task->account, task->channel,
task->to, task->body);
}
else
{
auto result = fmt::format("[nohttp] {}", err ? err : "NULL");
channel__send_message(task->account, task->channel,
task->to.data(), result.data());
}
xmpp_stanza_add_child(message, message__x);
xmpp_stanza_release(message__x);
delete task;
return WEECHAT_RC_OK;
};
struct t_hook *process_hook =
weechat_hook_process_hashtable(command.data(), options, timeout,
callback, task, nullptr);
weechat_hashtable_free(options);
(void) process_hook;
return WEECHAT_RC_OK;
} while(0);
}
xmpp_stanza_t *message__active = xmpp_stanza_new(account->context);

@ -1332,6 +1332,16 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
.build(account->context)
.get());
xmpp_send(conn, stanza::iq()
.from(account_jid(account))
.to(account_jid(account))
.type("get")
.id(stanza::uuid(account->context))
.rfc6121()
.query(stanza::rfc6121::query())
.build(account->context)
.get());
xmpp_send(conn, stanza::iq()
.from(account_jid(account))
.to(account_jid(account))

@ -29,11 +29,11 @@
"(" {
return token::LPAREN;
}
")" {
return token::RPAREN;
}
[\n \t\r]+ {
// Update line number
loc->lines();
@ -44,13 +44,13 @@
yylval->build<std::string>(yytext);
return token::STRING;
}
[^ "(:@)]+ {
yylval->build<std::string>(yytext);
return token::NAME;
}
. {
return *yytext;
}
%%
%%

@ -169,6 +169,7 @@ namespace stanza {
#include "xep-0115.inl"
#include "xep-0280.inl"
#include "xep-0319.inl"
#include "rfc-6121.inl"
namespace stanza {
struct body : virtual public spec {
@ -202,7 +203,8 @@ namespace stanza {
struct iq : virtual public spec,
public xep0030::iq,
public xep0049::iq,
public xep0280::iq {
public xep0280::iq,
public rfc6121::iq {
iq() : spec("iq") {}
iq& id(std::string_view s) { attr("id", s); return *this; }

@ -0,0 +1,34 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#pragma once
#include <optional>
#include <string>
#include "node.hh"
#pragma GCC visibility push(default)
#include "ns.hh"
#pragma GCC visibility pop
namespace stanza {
/* Instant Messaging and Presence */
struct rfc6121 {
struct query : virtual public spec {
query() : spec("query") {
xmlns<jabber::iq::roster>();
}
};
struct iq : virtual public spec {
iq() : spec("iq") {}
iq& rfc6121() { return *this; }
iq& query(rfc6121::query q = {}) { child(q); return *this; }
};
};
}
Loading…
Cancel
Save