Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/kruh.deno.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export const DINOSAUR_UID = "c838e77e8a599aba7d0b";

const SPOTIFY_QUERY_URL =
"https://api-partner.spotify.com/pathfinder/v2/query";
const SPOTIFY_AUTHORIZATION =
"Bearer BQCWnlfP-dGQG8eRiFRsdx0zBI_OHkgbjJ_FymeSGZaTuqdiVhMfs_YXgmwt7BoY_psA-up3vuHxTO602Yzob5LoqclAVHt11FHGuPPRXkbbQjX7QrrUulzSbom06S4_6H1jPyQeOKA";
const SPOTIFY_CLIENT_TOKEN =
"AACkhRToXk5jMT7VTSRuEBg6AHBv1c26/mL+wjmFSDPNAC5AOCAX9HNnTZrM0hlX15Ssyivgg8pXrMbAtZHuUJd7Kea/jUKErxKfSfoVpmR/vcYal9k1RoY8BVyGDil1Bgky9VQtEQok84jX1F/L7X9iUerfvA9QWjWbqRYCLnDsHOir5vrCMLDJMaYJZ4Q9zw3d3lr4MaBukKYUJPTWeQoSb+dM0udHyNlB8JeInu0WnYMiRCivU7g1gxgn9mLJ7Xw4KHvQEkqa/GokKVH/A56uI8I83hAXOaodOLmS+3yyQO/sLHY20QF07anVJVU5GEC0owsKvnJYhXkKgvQC7JADTUJgxAw=";

export async function getDinosaurPlaycount(): Promise<number | null> {
const request = await fetch(SPOTIFY_QUERY_URL, {
credentials: "include",
headers: {
"User-Agent":
"Mozilla/5.0 (X11; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0",
Accept: "application/json",
"Accept-Language": "en",
authorization: SPOTIFY_AUTHORIZATION,
"app-platform": "WebPlayer",
"spotify-app-version": "896000000",
"content-type": "application/json;charset=UTF-8",
"client-token": SPOTIFY_CLIENT_TOKEN,
"Sec-GPC": "1",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-site",
Priority: "u=4",
Pragma: "no-cache",
"Cache-Control": "no-cache",
},
referrer: "https://open.spotify.com/",
body:
"{\"variables\":{\"uri\":\"spotify:artist:7wwkwCP5b0waa5bhpZCDPq\",\"locale\":\"\",\"preReleaseV2\":false},\"operationName\":\"queryArtistOverview\",\"extensions\":{\"persistedQuery\":{\"version\":1,\"sha256Hash\":\"7f86ff63e38c24973a2842b672abe44c910c1973978dc8a4a0cb648edef34527\"}}}",
method: "POST",
mode: "cors",
});

if (!request.ok) {
console.error("Spotify request failed:", request.status);
return null;
}

const data = await request.json();
const topTracks = data?.data?.artistUnion?.discography?.topTracks?.items;
if (!Array.isArray(topTracks)) {
console.error("Unexpected Spotify response:", data);
return null;
}

const dinosaurItem = topTracks.find((track) => track?.uid === DINOSAUR_UID);
const playcountStr = dinosaurItem?.track?.playcount;
const playcount = Number(playcountStr);
if (!Number.isFinite(playcount)) {
console.error("Invalid playcount:", playcountStr);
return null;
}

return playcount;
}
68 changes: 68 additions & 0 deletions src/tg/bot.deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DOMAIN,
genRandomToken,
getFileBase64,
LLM_KEY,
MAIN_CHAT_ID,
shutUpState,
STICEKR_SET_NAME,
Expand All @@ -32,6 +33,10 @@ export function get_video(index: number): Uint8Array | null {
return videoList[index];
}

// Message history for /analysis command
const messageHistory: any[] = [];
const MAX_HISTORY = 30;

let sticekrs: any;
export async function getSticekrCount(): Promise<number> {
if (!sticekrs) {
Expand Down Expand Up @@ -133,6 +138,16 @@ export async function* handleTgUpdate(data: any) {
const text = data?.message?.text ?? data?.message?.caption;
if (typeof text !== "string") return;

// Store message for /analysis
if (data.message.chat.id === MAIN_CHAT_ID) {
messageHistory.push({
from: data.message.from?.first_name ?? "Anon",
text: text,
time: new Date().toISOString(),
});
if (messageHistory.length > MAX_HISTORY) messageHistory.shift();
}

const reactions = [
{ t: ["sex"], r: "🤨" },
{ t: ["rust", "růst"], r: "⚡" },
Expand Down Expand Up @@ -480,6 +495,15 @@ Be grateful for your abilities and your incredible success and your considerable
});
}

if (
(text.toLowerCase().includes("analýza") ||
text.toLowerCase().includes("analysis") ||
text.toLowerCase().includes("kowalski")) &&
data.message.chat.id === MAIN_CHAT_ID
) {
yield* handleAnalysis(data, 30);
}

if (text === "/kdo") {
const reply_id = data.message.reply_to_message?.message_id;
await tgCall(
Expand Down Expand Up @@ -869,6 +893,50 @@ async function* handleInlineQuery(data: any) {
}
}

async function* handleAnalysis(data: any, n: number) {
const recent = messageHistory.slice(-n);
const chatText = recent.map((m, i) => `#${i + 1} ${m.from}: ${m.text}`).join("\n\n");

const prompt = `Here is a transcript of ${n} recent messages from a group chat:

---
${chatText}
---

Analyze this conversation. What's going on? Who are the key players? Give your honest, slightly unhinged take on the dynamics. Be concise.`;

try {
const resp = await fetch("https://api.juan.bilej.monster/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${LLM_KEY}`,
},
body: JSON.stringify({
model: "qwen3-27b",
messages: [{ role: "user", content: prompt }],
max_tokens: 1024,
}),
});

const json = await resp.json();
const reply = json.choices?.[0]?.message?.content ?? "juan ded";

yield await tgCall({
chat_id: data.message.chat.id,
reply_to_message_id: data.message.message_id,
parse_mode: "MarkdownV2",
text: reply.replaceAll("\\", "\\\\").replaceAll("`", "\\`"),
});
} catch (e: any) {
yield await tgCall({
chat_id: data.message.chat.id,
reply_to_message_id: data.message.message_id,
text: `${e.message}`,
});
}
}

async function* sticekrThis(
orig_msg: any,
): AsyncGenerator<any, string | null, unknown> {
Expand Down
15 changes: 15 additions & 0 deletions src/tg/init.deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
webhookPath,
webhookUrlToken,
} from "./utils.deno.ts";
import { getDinosaurPlaycount } from "../kruh.deno.ts";
import { geohash } from "../geohash.deno.ts";
import {
getImageForPoint,
Expand Down Expand Up @@ -215,6 +216,7 @@ async function postGeohash() {
const bootId = genRandomToken(16);

let tempDir = "";
let dinosaurMillionAnnounced = false;

export function getTempDir() {
return tempDir;
Expand Down Expand Up @@ -290,5 +292,18 @@ export async function init() {
}
});

Deno.cron("jakej je tvuj", "*/30 * * * *", async () => {
if (dinosaurMillionAnnounced) return;
const playcount = await getDinosaurPlaycount();
if (playcount === null) return;
if (playcount >= 1_000_000) {
dinosaurMillionAnnounced = true;
await tgCall({
chat_id: MAIN_CHAT_ID,
text: 'Dinosaur má milion na Spotify!!',
});
}
});

postGeohash();
}
1 change: 1 addition & 0 deletions src/tg/utils.deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const DOMAIN = Deno.env.get("DOMAIN")!;
export const STICEKR_SET_NAME = Deno.env.get("STICKER_SET_NAME")!;
export const STICEKR_SET_OWNER = parseInt(Deno.env.get("STICKER_SET_OWNER")!);
export const PRINTER_TOKEN = Deno.env.get("PRINTER_TOKEN")!;
export const LLM_KEY = Deno.env.get("LLM_KEY")!;

export const webhookPath = "/tg-webhook";

Expand Down
Loading