feat(caps): add cache clearing to /caps

Add /caps clear to wipe the local capabilities cache.
Implement autocomplete for new subcommand.
This commit is contained in:
2026-07-09 15:19:07 +00:00
parent 756d4e18cf
commit 60e088ac3c
6 changed files with 68 additions and 4 deletions

View File

@@ -42,6 +42,7 @@
#include "ai/ai_client.h"
static char* _caps_autocomplete(ProfWin* window, const char* const input, gboolean previous);
static char* _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous);
static char* _notify_autocomplete(ProfWin* window, const char* const input, gboolean previous);
static char* _theme_autocomplete(ProfWin* window, const char* const input, gboolean previous);
@@ -151,6 +152,7 @@ static Autocomplete account_clear_ac;
static Autocomplete account_default_ac;
static Autocomplete account_status_ac;
static Autocomplete disco_ac;
static Autocomplete caps_subcommands_ac;
static Autocomplete wins_ac;
static Autocomplete roster_ac;
static Autocomplete roster_show_ac;
@@ -321,6 +323,7 @@ static Autocomplete* all_acs[] = {
&account_default_ac,
&account_status_ac,
&disco_ac,
&caps_subcommands_ac,
&wins_ac,
&roster_ac,
&roster_show_ac,
@@ -597,6 +600,8 @@ cmd_ac_init(void)
autocomplete_add(disco_ac, "info");
autocomplete_add(disco_ac, "items");
autocomplete_add(caps_subcommands_ac, "clear");
autocomplete_add(account_ac, "list");
autocomplete_add(account_ac, "show");
autocomplete_add(account_ac, "add");
@@ -1414,6 +1419,7 @@ cmd_ac_init(void)
g_hash_table_insert(ac_funcs, "/ban", _ban_autocomplete);
g_hash_table_insert(ac_funcs, "/blocked", _blocked_autocomplete);
g_hash_table_insert(ac_funcs, "/bookmark", _bookmark_autocomplete);
g_hash_table_insert(ac_funcs, "/caps", _caps_autocomplete);
g_hash_table_insert(ac_funcs, "/clear", _clear_autocomplete);
g_hash_table_insert(ac_funcs, "/close", _close_autocomplete);
g_hash_table_insert(ac_funcs, "/cmd", _adhoc_cmd_autocomplete);
@@ -1985,6 +1991,35 @@ _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previ
return NULL;
}
static char*
_caps_autocomplete(ProfWin* window, const char* const input, gboolean previous)
{
char* result = NULL;
result = autocomplete_param_with_ac(input, "/caps", caps_subcommands_ac, TRUE, previous);
if (result) {
return result;
}
if (window->type == WIN_MUC) {
ProfMucWin* mucwin = (ProfMucWin*)window;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
if (nick_ac) {
result = autocomplete_param_with_ac(input, "/caps", nick_ac, TRUE, previous);
}
} else if (connection_get_status() == JABBER_CONNECTED) {
result = autocomplete_param_with_func(input, "/caps", roster_contact_autocomplete, previous, NULL);
if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/caps", roster_barejid_autocomplete, previous, NULL);
if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/caps", roster_fulljid_autocomplete, previous, NULL);
}
return result;
}
static char*
_sub_autocomplete(ProfWin* window, const char* const input, gboolean previous)
{

View File

@@ -427,17 +427,21 @@ static const struct cmd_t command_defs[] = {
CMD_TAG_GROUPCHAT)
CMD_SYN(
"/caps",
"/caps <fulljid>|<nick>")
"/caps <fulljid>|<nick>",
"/caps clear")
CMD_DESC(
"Find out a contacts, or room members client software capabilities. "
"If in private chat initiated from a chat room, no parameter is required.")
"If in private chat initiated from a chat room, no parameter is required. "
"Use clear to remove all cached capabilities.")
CMD_ARGS(
{ "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see capabilities." },
{ "<nick>", "If in a chat room, nickname for which you wish to see capabilities." })
{ "<nick>", "If in a chat room, nickname for which you wish to see capabilities." },
{ "clear", "Clear all cached capabilities." })
CMD_EXAMPLES(
"/caps ran@cold.sea.org/laptop",
"/caps ran@cold.sea.org/phone",
"/caps aegir")
"/caps aegir",
"/caps clear")
},
{ CMD_PREAMBLE("/software",

View File

@@ -70,6 +70,7 @@
#include "xmpp/stanza.h"
#include "xmpp/vcard_funcs.h"
#include "xmpp/xmpp.h"
#include "xmpp/capabilities.h"
#ifdef HAVE_LIBOTR
#include "otr/otr.h"
@@ -3387,6 +3388,12 @@ cmd_caps(ProfWin* window, const char* const command, gchar** args)
return TRUE;
}
if (g_strcmp0(args[0], "clear") == 0) {
caps_cache_clear();
cons_show("Capabilities cache cleared.");
return TRUE;
}
switch (window->type) {
case WIN_MUC:
if (args[0]) {
@@ -3405,6 +3412,7 @@ cmd_caps(ProfWin* window, const char* const command, gchar** args)
break;
case WIN_CHAT:
case WIN_CONSOLE:
case WIN_XML:
if (args[0]) {
auto_jid Jid* jid = jid_create(args[0]);

View File

@@ -23,6 +23,7 @@
#include "plugins/plugins.h"
#include "config/files.h"
#include "config/preferences.h"
#include "xmpp/connection.h"
#include "xmpp/xmpp.h"
#include "xmpp/stanza.h"
#include "xmpp/form.h"
@@ -271,6 +272,16 @@ caps_map_jid_to_ver(const char* const jid, const char* const ver)
g_hash_table_insert(jid_to_ver, strdup(jid), strdup(ver));
}
void
caps_cache_clear(void)
{
g_hash_table_remove_all(jid_to_ver);
g_hash_table_remove_all(jid_to_caps);
cache = g_key_file_new();
caps_prof_keyfile.keyfile = cache;
save_keyfile(&caps_prof_keyfile);
}
gboolean
caps_cache_contains(const char* const ver)
{

View File

@@ -28,5 +28,6 @@ void caps_map_jid_to_ver(const char* const jid, const char* const ver);
gboolean caps_cache_contains(const char* const ver);
GList* caps_get_features(void);
char* caps_get_my_sha1(xmpp_ctx_t* const ctx);
void caps_cache_clear(void);
#endif

View File

@@ -500,6 +500,11 @@ caps_jid_has_feature(const char* const jid, const char* const feature)
return FALSE;
}
void
caps_cache_clear(void)
{
}
gboolean
bookmark_add(const char* jid, const char* nick, const char* password, const char* autojoin_str, const char* name)
{