teleton 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,176 @@
1
+ // src/agent/tools/telegram/gifts/get-my-gifts.ts
2
+ import { Type } from "@sinclair/typebox";
3
+ import { Api } from "telegram";
4
+ function extractEmoji(sticker) {
5
+ if (!sticker?.attributes) return null;
6
+ const attr = sticker.attributes.find(
7
+ (a) => a.className === "DocumentAttributeSticker" || a.className === "DocumentAttributeCustomEmoji"
8
+ );
9
+ return attr?.alt || null;
10
+ }
11
+ var telegramGetMyGiftsTool = {
12
+ name: "telegram_get_my_gifts",
13
+ description: `Get Star Gifts you or another user has received.
14
+
15
+ USAGE:
16
+ - To view YOUR OWN gifts: omit both userId and viewSender
17
+ - To view the SENDER's gifts (when user says "show me MY gifts"): set viewSender=true
18
+ - To view a specific user's gifts: pass their userId
19
+
20
+ PRESENTATION GUIDE:
21
+ - For collectibles: Use "title + model" as display name (e.g., "Hypno Lollipop Telegram")
22
+ - NFT link: t.me/nft/{slug} (e.g., t.me/nft/HypnoLollipop-63414)
23
+ - Respond concisely: "You have a Hypno Lollipop Telegram \u{1F36D}"
24
+ - Only give details (rarity, backdrop, pattern) when specifically asked
25
+ - attributes.model.name = model, attributes.pattern.name = pattern, attributes.backdrop.name = backdrop
26
+ - rarityPermille: divide by 10 to get percentage (7 = 0.7%)
27
+
28
+ TRANSFER: Use msgId (for your own gifts) to transfer collectibles via telegram_transfer_collectible.
29
+
30
+ NEVER dump all raw data. Keep responses natural and concise.`,
31
+ parameters: Type.Object({
32
+ userId: Type.Optional(
33
+ Type.String({
34
+ description: "User ID to get gifts for. Use viewSender=true instead if looking at the message sender's gifts."
35
+ })
36
+ ),
37
+ viewSender: Type.Optional(
38
+ Type.Boolean({
39
+ description: "Set to true to view the message sender's gifts (when user says 'show me MY gifts'). Takes precedence over userId."
40
+ })
41
+ ),
42
+ limit: Type.Optional(
43
+ Type.Number({
44
+ description: "Maximum number of gifts to return (default: 50)",
45
+ minimum: 1,
46
+ maximum: 200
47
+ })
48
+ ),
49
+ excludeUnsaved: Type.Optional(
50
+ Type.Boolean({
51
+ description: "Only show gifts saved/displayed on profile"
52
+ })
53
+ ),
54
+ excludeSaved: Type.Optional(
55
+ Type.Boolean({
56
+ description: "Only show gifts NOT displayed on profile"
57
+ })
58
+ ),
59
+ sortByValue: Type.Optional(
60
+ Type.Boolean({
61
+ description: "Sort by value instead of date. Default: false (sorted by date)"
62
+ })
63
+ )
64
+ })
65
+ };
66
+ var telegramGetMyGiftsExecutor = async (params, context) => {
67
+ try {
68
+ const { userId, viewSender, limit = 50, excludeUnsaved, excludeSaved, sortByValue = false } = params;
69
+ const gramJsClient = context.bridge.getClient().getClient();
70
+ const targetUserId = viewSender ? context.senderId.toString() : userId;
71
+ const peer = targetUserId ? await gramJsClient.getEntity(targetUserId) : new Api.InputPeerSelf();
72
+ const catalog = await gramJsClient.invoke(
73
+ new Api.payments.GetStarGifts({ hash: 0 })
74
+ );
75
+ const catalogMap = /* @__PURE__ */ new Map();
76
+ for (const catalogGift of catalog.gifts || []) {
77
+ const id = catalogGift.id?.toString();
78
+ if (id) {
79
+ catalogMap.set(id, {
80
+ limited: catalogGift.limited || false,
81
+ soldOut: catalogGift.soldOut || false,
82
+ emoji: extractEmoji(catalogGift.sticker),
83
+ availabilityTotal: catalogGift.availabilityTotal,
84
+ availabilityRemains: catalogGift.availabilityRemains
85
+ });
86
+ }
87
+ }
88
+ const result = await gramJsClient.invoke(
89
+ new Api.payments.GetSavedStarGifts({
90
+ peer,
91
+ offset: "",
92
+ limit,
93
+ excludeUnsaved,
94
+ excludeSaved,
95
+ sortByValue
96
+ })
97
+ );
98
+ const gifts = (result.gifts || []).map((savedGift) => {
99
+ const gift = savedGift.gift;
100
+ const isCollectible = gift?.className === "StarGiftUnique";
101
+ const lookupId = isCollectible ? gift.giftId?.toString() : gift.id?.toString();
102
+ const catalogInfo = catalogMap.get(lookupId);
103
+ const isLimited = isCollectible || catalogInfo?.limited === true;
104
+ const extractAttrSummary = (attr) => attr ? {
105
+ name: attr.name,
106
+ rarityPercent: attr.rarityPermille ? (attr.rarityPermille / 10).toFixed(1) + "%" : null
107
+ } : null;
108
+ const compactGift = {
109
+ date: savedGift.date,
110
+ isLimited,
111
+ isCollectible,
112
+ stars: gift?.stars?.toString(),
113
+ emoji: catalogInfo?.emoji || null,
114
+ // IDs needed for transfer/actions (msgId for user gifts, savedId for chat gifts)
115
+ msgId: savedGift.msgId,
116
+ savedId: savedGift.savedId?.toString(),
117
+ // Transfer cost in Stars (if set, transfer requires payment; if null, transfer is free)
118
+ transferStars: savedGift.transferStars?.toString() || null
119
+ };
120
+ if (isCollectible) {
121
+ compactGift.collectibleId = gift.id?.toString();
122
+ compactGift.title = gift.title;
123
+ compactGift.num = gift.num;
124
+ compactGift.slug = gift.slug;
125
+ compactGift.nftLink = `t.me/nft/${gift.slug}`;
126
+ const modelAttr = gift.attributes?.find((a) => a.className === "StarGiftAttributeModel");
127
+ const patternAttr = gift.attributes?.find((a) => a.className === "StarGiftAttributePattern");
128
+ const backdropAttr = gift.attributes?.find((a) => a.className === "StarGiftAttributeBackdrop");
129
+ compactGift.model = extractAttrSummary(modelAttr);
130
+ compactGift.pattern = extractAttrSummary(patternAttr);
131
+ compactGift.backdrop = extractAttrSummary(backdropAttr);
132
+ } else {
133
+ compactGift.canUpgrade = savedGift.canUpgrade || false;
134
+ if (savedGift.canUpgrade) {
135
+ compactGift.upgradeStars = gift?.upgradeStars?.toString();
136
+ }
137
+ }
138
+ if (isLimited && !isCollectible) {
139
+ compactGift.availabilityRemains = catalogInfo?.availabilityRemains || gift?.availabilityRemains;
140
+ compactGift.availabilityTotal = catalogInfo?.availabilityTotal || gift?.availabilityTotal;
141
+ }
142
+ return compactGift;
143
+ });
144
+ const limited = gifts.filter((g) => g.isLimited);
145
+ const unlimited = gifts.filter((g) => !g.isLimited);
146
+ const collectibles = gifts.filter((g) => g.isCollectible);
147
+ const viewingLabel = viewSender ? `sender (${context.senderId})` : userId || "self";
148
+ console.log(`\u{1F4E6} get_my_gifts: viewing ${viewingLabel}, found ${gifts.length} gifts (${collectibles.length} collectibles)`);
149
+ return {
150
+ success: true,
151
+ data: {
152
+ viewingUser: targetUserId || "self",
153
+ gifts,
154
+ summary: {
155
+ total: gifts.length,
156
+ limited: limited.length,
157
+ unlimited: unlimited.length,
158
+ collectibles: collectibles.length,
159
+ canUpgrade: gifts.filter((g) => g.canUpgrade).length
160
+ },
161
+ totalCount: result.count
162
+ }
163
+ };
164
+ } catch (error) {
165
+ console.error("Error getting gifts:", error);
166
+ return {
167
+ success: false,
168
+ error: error instanceof Error ? error.message : String(error)
169
+ };
170
+ }
171
+ };
172
+
173
+ export {
174
+ telegramGetMyGiftsTool,
175
+ telegramGetMyGiftsExecutor
176
+ };