-
-
Notifications
You must be signed in to change notification settings - Fork 5
feat(messaging): Discord channel read + summarize (on-demand + scheduled digest) #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
279abc7
ci: trim pre-push to fast tests; satellite + daemon smoke live in CI …
KerseyFabrications 9ee21cb
feat(messaging): Discord channel read + summarize (on-demand + schedu…
KerseyFabrications 1780f3f
fix(messaging): review hardening for Discord read (injection, 429, caps)
KerseyFabrications 5800d3b
fix(messaging): address Copilot + Qodo PR review (security, reliabili…
KerseyFabrications File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /* | ||
| * This program 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, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program 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 this program. If not, see <https://www.gnu.org/licenses/>. | ||
| * | ||
| * By contributing to this project, you agree to license your contributions | ||
| * under the GPLv3 (or any later version) or any future licenses chosen by | ||
| * the project author(s). | ||
| * | ||
| * Scheduled-origin context — a thread-local marker the scheduler sets around | ||
| * a scheduled tool-callback invocation so tools can (a) recover the owning | ||
| * user_id (the scheduler thread has no session, so session_get_command_context | ||
| * returns NULL and tools would otherwise fall back to user 1) and (b) gate | ||
| * which actions may run unattended. Layer 1 / Foundation: libc only, no DAWN | ||
| * state, always compiled. | ||
| */ | ||
| #ifndef SCHEDULED_CONTEXT_H | ||
| #define SCHEDULED_CONTEXT_H | ||
|
|
||
| #include <stdbool.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
| * @brief Mark the current thread as executing on behalf of @p user_id from a | ||
| * scheduled (briefing/task) context. Pair with scheduled_context_clear. | ||
| * | ||
| * @param user_id Owning user (> 0). | ||
| */ | ||
| void scheduled_context_set(int user_id); | ||
|
|
||
| /** | ||
| * @brief Clear the scheduled-origin marker for the current thread. | ||
| */ | ||
| void scheduled_context_clear(void); | ||
|
|
||
| /** | ||
| * @brief Query whether the current thread is in a scheduled-origin scope. | ||
| * | ||
| * @param user_id_out If non-NULL, set to the scheduled user_id (0 when not in | ||
| * a scheduled scope). | ||
| * @return true if currently executing in a scheduled-origin scope. | ||
| */ | ||
| bool scheduled_context_get(int *user_id_out); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif /* SCHEDULED_CONTEXT_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /* | ||
| * This program 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, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program 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 this program. If not, see <https://www.gnu.org/licenses/>. | ||
| * | ||
| * By contributing to this project, you agree to license your contributions | ||
| * under the GPLv3 (or any later version) or any future licenses chosen by | ||
| * the project author(s). | ||
| * | ||
| * Lightweight fuzzy name matcher — shared by surfaces that resolve a | ||
| * user-typed name (Home Assistant entities, Discord channels, ...) against | ||
| * a list of candidate names. Layer 1 / Foundation: depends only on libc, | ||
| * no DAWN state. Extracted from the byte-identical helper that previously | ||
| * lived static in homeassistant_service.c. | ||
| */ | ||
|
|
||
| #ifndef STR_FUZZY_H | ||
| #define STR_FUZZY_H | ||
|
|
||
| #include <stddef.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /* Score tiers returned by str_fuzzy_score(). */ | ||
| #define STR_FUZZY_SCORE_EXACT 100 /* candidate == needle */ | ||
| #define STR_FUZZY_SCORE_CONTAINS 80 /* candidate contains needle as substring */ | ||
| #define STR_FUZZY_SCORE_TOKEN_BONUS 20 /* per whitespace-delimited needle token found */ | ||
|
|
||
| /** | ||
| * @brief Lowercase @p src into @p dst (ASCII tolower), bounded by @p max_len. | ||
| * | ||
| * Always NUL-terminates within @p max_len. Intended to pre-normalize both | ||
| * candidate and needle strings before scoring. | ||
| * | ||
| * @param dst Output buffer. | ||
| * @param src Source string. | ||
| * @param max_len Size of @p dst (must be >= 1). | ||
| */ | ||
| void str_fuzzy_tolower(char *dst, const char *src, size_t max_len); | ||
|
|
||
| /** | ||
| * @brief Score how well @p needle_lower matches @p haystack_lower. | ||
| * | ||
| * Both arguments MUST already be lowercased (see str_fuzzy_tolower()). | ||
| * Tiered, allocation-free scoring: | ||
| * - 100 exact match | ||
| * - 80 haystack contains needle as a substring | ||
| * - +20 per whitespace-delimited needle token found in haystack | ||
| * | ||
| * The tiers are not mutually exclusive in spirit but return early: an exact | ||
| * or substring hit short-circuits before token scoring. Callers compare | ||
| * scores across candidates and apply their own acceptance threshold. | ||
| * | ||
| * @param haystack_lower Candidate name, lowercased. | ||
| * @param needle_lower User-supplied query, lowercased. | ||
| * @return Match score (0 = no overlap; higher is better). | ||
| */ | ||
| int str_fuzzy_score(const char *haystack_lower, const char *needle_lower); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif /* STR_FUZZY_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| /* | ||
| * This program 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, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program 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 this program. If not, see <https://www.gnu.org/licenses/>. | ||
| * | ||
| * By contributing to this project, you agree to license your contributions | ||
| * under the GPLv3 (or any later version) or any future licenses chosen by | ||
| * the project author(s). | ||
| * | ||
| * Discord driver — INTERNAL shared surface. Private to the | ||
| * src/messaging/messaging_discord*.c translation units; lets the | ||
| * channel-history READ path (messaging_discord_read.c) share the bot token, | ||
| * snowflake validation, and REST constants with the gateway/send core | ||
| * (messaging_discord.c) after the file was split for size. NOT a public API — | ||
| * external code uses include/messaging/messaging_discord.h. | ||
| */ | ||
| #ifndef MESSAGING_DISCORD_INTERNAL_H | ||
| #define MESSAGING_DISCORD_INTERNAL_H | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
|
|
||
| #include "messaging/messaging_driver.h" /* messaging_read_window_t */ | ||
|
|
||
| /* REST surface shared by the send core and the read path. */ | ||
| #define DC_BOT_TOKEN_MAX 256 | ||
| #define DC_REST_BASE_URL "https://discord.com/api/v10" | ||
| #define DC_USER_AGENT "DAWN-Discord/0.1 (libcurl, libwebsockets)" | ||
| #define DC_SNOWFLAKE_MAX_DIGITS 20 /* a 64-bit snowflake is <= 20 digits */ | ||
|
|
||
| /* Bot token — defined in messaging_discord.c, read by the REST surfaces. */ | ||
| extern char s_bot_token[DC_BOT_TOKEN_MAX]; | ||
|
|
||
| /** | ||
| * @brief Validate a Discord snowflake: decimal digits only, <= 20 of them. | ||
| * | ||
| * Shared defense-in-depth gate before any id is interpolated into a REST URL, | ||
| * and a length cap so a downstream strtoull() can't silently saturate. Inline | ||
| * so both translation units get a copy without a cross-TU symbol. | ||
| */ | ||
| static inline bool dc_is_valid_snowflake(const char *s) { | ||
| if (!s || !s[0]) { | ||
| return false; | ||
| } | ||
| size_t i; | ||
| for (i = 0; s[i] != '\0'; i++) { | ||
| /* Fail fast on over-length input — don't walk an arbitrarily long | ||
| * attacker-controlled string just to reject it. */ | ||
| if (i >= DC_SNOWFLAKE_MAX_DIGITS) { | ||
| return false; | ||
| } | ||
| if (s[i] < '0' || s[i] > '9') { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /* Read path — defined in messaging_discord_read.c, wired into the driver | ||
| * descriptor in messaging_discord.c. */ | ||
| int dc_list_readable_channels(char **out_json); | ||
| int dc_read_history(const char *channel_id, const messaging_read_window_t *window, char **out_json); | ||
| void dc_invalidate_channel_cache(void); /* drop discovery cache (recover from miss) */ | ||
| void dc_read_shutdown(void); /* free the read CURL handle + discovery cache */ | ||
|
|
||
| #endif /* MESSAGING_DISCORD_INTERNAL_H */ |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.