Feat: Add Discord integration and refine abbreviation handling
This commit is contained in:
@@ -21,12 +21,13 @@ Given a YouTube URL, the app can:
|
|||||||
- generate an English summary with a local Ollama model
|
- generate an English summary with a local Ollama model
|
||||||
- optionally translate that summary into German and Japanese
|
- optionally translate that summary into German and Japanese
|
||||||
- store the results locally so they can be reopened later
|
- store the results locally so they can be reopened later
|
||||||
|
- optionally send individual summaries to Discord with a user-provided webhook URL
|
||||||
|
|
||||||
## Local-Only Behavior
|
## Local-Only Behavior
|
||||||
|
|
||||||
This repository is intentionally reset to a clean publishable state:
|
This repository is intentionally reset to a clean publishable state:
|
||||||
|
|
||||||
- no Discord webhook integration
|
- no bundled Discord webhook URL or production credentials
|
||||||
- no remote PHP/MySQL sync
|
- no remote PHP/MySQL sync
|
||||||
- no bundled production data or pre-filled database
|
- no bundled production data or pre-filled database
|
||||||
- runtime data is stored in the OS app data directory, not in the repo
|
- runtime data is stored in the OS app data directory, not in the repo
|
||||||
|
|||||||
@@ -814,13 +814,13 @@ fn is_word_char(ch: char) -> bool {
|
|||||||
|
|
||||||
fn is_abbreviation(token: &str) -> bool {
|
fn is_abbreviation(token: &str) -> bool {
|
||||||
const ABBREVIATIONS: &[&str] = &[
|
const ABBREVIATIONS: &[&str] = &[
|
||||||
"mr.", "mrs.", "ms.", "dr.", "prof.", "sr.", "jr.", "st.", "vs.", "etc.", "e.g.",
|
"mr.", "mrs.", "ms.", "dr.", "prof.", "sr.", "jr.", "st.", "vs.", "etc.", "e.g.", "i.e.",
|
||||||
"i.e.", "cf.", "al.", "a.m.", "p.m.", "jan.", "feb.", "mar.", "apr.", "jun.", "jul.",
|
"cf.", "al.", "a.m.", "p.m.", "jan.", "feb.", "mar.", "apr.", "jun.", "jul.", "aug.",
|
||||||
"aug.", "sep.", "sept.", "oct.", "nov.", "dec.", "no.", "fig.", "eq.", "vol.", "rev.",
|
"sep.", "sept.", "oct.", "nov.", "dec.", "no.", "fig.", "eq.", "vol.", "rev.", "gen.",
|
||||||
"gen.", "gov.", "sen.", "rep.", "dept.", "univ.", "inc.", "ltd.", "co.", "corp.",
|
"gov.", "sen.", "rep.", "dept.", "univ.", "inc.", "ltd.", "co.", "corp.", "bros.",
|
||||||
"bros.", "approx.", "est.", "min.", "sec.", "hr.", "fr.", "bzw.", "z.b.", "d.h.",
|
"approx.", "est.", "min.", "sec.", "hr.", "fr.", "bzw.", "z.b.", "d.h.", "u.a.", "u.u.",
|
||||||
"u.a.", "u.u.", "i.d.r.", "ca.", "ggf.", "vgl.", "evtl.", "sog.", "u.s.w.", "nr.",
|
"i.d.r.", "ca.", "ggf.", "vgl.", "evtl.", "sog.", "u.s.w.", "nr.", "abs.", "art.", "s.",
|
||||||
"abs.", "art.", "s.", "ff.", "mio.", "mrd.", "sek.", "okt.", "dez.",
|
"ff.", "mio.", "mrd.", "sek.", "okt.", "dez.",
|
||||||
];
|
];
|
||||||
ABBREVIATIONS.contains(&token)
|
ABBREVIATIONS.contains(&token)
|
||||||
}
|
}
|
||||||
@@ -874,10 +874,7 @@ fn insert_sentence_line_breaks(text: &str) -> String {
|
|||||||
while j > 0 && is_word_char(chars[j - 1]) {
|
while j > 0 && is_word_char(chars[j - 1]) {
|
||||||
j -= 1;
|
j -= 1;
|
||||||
}
|
}
|
||||||
let token = chars[j..=i]
|
let token = chars[j..=i].iter().collect::<String>().to_ascii_lowercase();
|
||||||
.iter()
|
|
||||||
.collect::<String>()
|
|
||||||
.to_ascii_lowercase();
|
|
||||||
if ch == '.' && is_abbreviation(&token) {
|
if ch == '.' && is_abbreviation(&token) {
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -1124,7 +1121,7 @@ fn build_discord_messages(
|
|||||||
chunks.splice(0..1, first_parts);
|
chunks.splice(0..1, first_parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if chunks.len() > 1 && char_len(chunks.last().unwrap_or(&String::new())) > last_limit {
|
if chunks.len() > 1 && chunks.last().map(|chunk| char_len(chunk)).unwrap_or(0) > last_limit {
|
||||||
let last_index = chunks.len() - 1;
|
let last_index = chunks.len() - 1;
|
||||||
let last_parts = split_summary_into_chunks(&chunks[last_index], last_limit);
|
let last_parts = split_summary_into_chunks(&chunks[last_index], last_limit);
|
||||||
chunks.splice(last_index.., last_parts);
|
chunks.splice(last_index.., last_parts);
|
||||||
@@ -1217,12 +1214,8 @@ fn post_summary_to_discord(
|
|||||||
let channel_text_line = limit_chars(&channel_name, 300);
|
let channel_text_line = limit_chars(&channel_name, 300);
|
||||||
let video_line = limit_chars(&format!("Video: {video_url}"), 700);
|
let video_line = limit_chars(&format!("Video: {video_url}"), 700);
|
||||||
let summary_text = format_summary_for_discord(summary);
|
let summary_text = format_summary_for_discord(summary);
|
||||||
let messages = build_discord_messages(
|
let messages =
|
||||||
&title_line,
|
build_discord_messages(&title_line, &channel_text_line, &video_line, &summary_text);
|
||||||
&channel_text_line,
|
|
||||||
&video_line,
|
|
||||||
&summary_text,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (index, message) in messages.iter().enumerate() {
|
for (index, message) in messages.iter().enumerate() {
|
||||||
post_discord_message(client, webhook_url, message)?;
|
post_discord_message(client, webhook_url, message)?;
|
||||||
@@ -1459,6 +1452,17 @@ async fn translate_summary(
|
|||||||
.map_err(|err| format!("Translate task failed: {err}"))?
|
.map_err(|err| format!("Translate task failed: {err}"))?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn send_summary_to_discord(
|
||||||
|
state: State<'_, AppState>,
|
||||||
|
request: SendSummaryToDiscordRequest,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let state = state.inner().clone();
|
||||||
|
tauri::async_runtime::spawn_blocking(move || send_summary_to_discord_inner(&state, request))
|
||||||
|
.await
|
||||||
|
.map_err(|err| format!("Discord task failed: {err}"))?
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn open_external(url: String) -> Result<(), String> {
|
fn open_external(url: String) -> Result<(), String> {
|
||||||
that(url).map_err(|err| format!("Failed to open URL: {err}"))
|
that(url).map_err(|err| format!("Failed to open URL: {err}"))
|
||||||
@@ -1531,6 +1535,7 @@ fn main() {
|
|||||||
summarize_video,
|
summarize_video,
|
||||||
delete_summary,
|
delete_summary,
|
||||||
translate_summary,
|
translate_summary,
|
||||||
|
send_summary_to_discord,
|
||||||
open_external,
|
open_external,
|
||||||
open_file
|
open_file
|
||||||
])
|
])
|
||||||
|
|||||||
Reference in New Issue
Block a user