@udondan/duolingo 1.0.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.
- package/LICENSE +21 -0
- package/README.md +373 -0
- package/dist/client/duolingo.d.ts +170 -0
- package/dist/client/duolingo.d.ts.map +1 -0
- package/dist/client/duolingo.js +499 -0
- package/dist/client/duolingo.js.map +1 -0
- package/dist/client/errors.d.ts +24 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +41 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/types.d.ts +272 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +6 -0
- package/dist/client/types.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +40 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/account.d.ts +10 -0
- package/dist/tools/account.d.ts.map +1 -0
- package/dist/tools/account.js +746 -0
- package/dist/tools/account.js.map +1 -0
- package/dist/tools/helpers.d.ts +18 -0
- package/dist/tools/helpers.d.ts.map +1 -0
- package/dist/tools/helpers.js +83 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/language.d.ts +11 -0
- package/dist/tools/language.d.ts.map +1 -0
- package/dist/tools/language.js +611 -0
- package/dist/tools/language.js.map +1 -0
- package/dist/tools/shop.d.ts +8 -0
- package/dist/tools/shop.d.ts.map +1 -0
- package/dist/tools/shop.js +125 -0
- package/dist/tools/shop.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for Duolingo REST API response shapes.
|
|
3
|
+
* Based on the unofficial Duolingo API at https://www.duolingo.com/users/<username>
|
|
4
|
+
*/
|
|
5
|
+
export interface DuolingoCalendarEntry {
|
|
6
|
+
datetime: number;
|
|
7
|
+
improvement: number;
|
|
8
|
+
event_type?: string | null;
|
|
9
|
+
skill_id?: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface DuolingoSkill {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
title: string;
|
|
15
|
+
learned: boolean;
|
|
16
|
+
strength: number;
|
|
17
|
+
progress_percent: number;
|
|
18
|
+
words: string[];
|
|
19
|
+
dependencies_name: string[];
|
|
20
|
+
dependency_order?: number;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface DuolingoLanguageData {
|
|
24
|
+
streak: number;
|
|
25
|
+
language_string: string;
|
|
26
|
+
level_progress: number;
|
|
27
|
+
num_skills_learned: number;
|
|
28
|
+
level_percent: number;
|
|
29
|
+
level_points: number;
|
|
30
|
+
next_level: number;
|
|
31
|
+
level_left: number;
|
|
32
|
+
language: string;
|
|
33
|
+
points: number;
|
|
34
|
+
fluency_score: number | null;
|
|
35
|
+
level: number;
|
|
36
|
+
calendar: DuolingoCalendarEntry[];
|
|
37
|
+
skills: DuolingoSkill[];
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
export interface DuolingoLanguage {
|
|
41
|
+
language: string;
|
|
42
|
+
language_string: string;
|
|
43
|
+
learning: boolean;
|
|
44
|
+
current_learning: boolean;
|
|
45
|
+
level: number;
|
|
46
|
+
points: number;
|
|
47
|
+
streak: number;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
export interface DuolingoTrackingProperties {
|
|
51
|
+
num_followers?: number;
|
|
52
|
+
num_following?: number;
|
|
53
|
+
streak?: number;
|
|
54
|
+
gems?: number;
|
|
55
|
+
[key: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
export interface DuolingoUserData {
|
|
58
|
+
username: string;
|
|
59
|
+
bio: string;
|
|
60
|
+
id: number;
|
|
61
|
+
cohort: number | null;
|
|
62
|
+
learning_language_string: string;
|
|
63
|
+
/** Returns human-readable relative text. Use creation_date for ISO string. */
|
|
64
|
+
created?: string;
|
|
65
|
+
/** ISO date string e.g. "2025-08-07T17:13:57". */
|
|
66
|
+
creation_date?: string;
|
|
67
|
+
/** Unix ms timestamp. */
|
|
68
|
+
created_dt?: number;
|
|
69
|
+
gplus_id?: string;
|
|
70
|
+
twitter_id?: string;
|
|
71
|
+
admin: boolean;
|
|
72
|
+
location: string | null;
|
|
73
|
+
fullname: string;
|
|
74
|
+
avatar: string;
|
|
75
|
+
ui_language: string;
|
|
76
|
+
daily_goal: number | null;
|
|
77
|
+
site_streak: number;
|
|
78
|
+
streak_extended_today: boolean;
|
|
79
|
+
notify_comment: boolean;
|
|
80
|
+
deactivated: boolean;
|
|
81
|
+
tts_base_url?: string;
|
|
82
|
+
tracking_properties?: DuolingoTrackingProperties;
|
|
83
|
+
calendar: DuolingoCalendarEntry[];
|
|
84
|
+
languages: DuolingoLanguage[];
|
|
85
|
+
language_data: Record<string, DuolingoLanguageData>;
|
|
86
|
+
[key: string]: unknown;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A course entry from the 2023-05-23 API.
|
|
90
|
+
* Covers language courses as well as non-language subjects (math, chess, music).
|
|
91
|
+
*/
|
|
92
|
+
export interface DuolingoCourse {
|
|
93
|
+
id: string;
|
|
94
|
+
/** Subject type: 'language' | 'math' | 'chess' | 'music' */
|
|
95
|
+
subject: string;
|
|
96
|
+
/** Short topic code, e.g. 'es', 'bt' (math), 'ch' (chess), 'mt' (music). */
|
|
97
|
+
topic: string;
|
|
98
|
+
xp: number;
|
|
99
|
+
fromLanguage: string;
|
|
100
|
+
/** Only present for language courses. */
|
|
101
|
+
learningLanguage?: string;
|
|
102
|
+
/** Only present for language courses. */
|
|
103
|
+
title?: string;
|
|
104
|
+
/** Only present for language courses. */
|
|
105
|
+
authorId?: string;
|
|
106
|
+
[key: string]: unknown;
|
|
107
|
+
}
|
|
108
|
+
export interface DuolingoStreakInfo {
|
|
109
|
+
length: number;
|
|
110
|
+
lastExtendedDate?: string;
|
|
111
|
+
startDate?: string;
|
|
112
|
+
endDate?: string;
|
|
113
|
+
}
|
|
114
|
+
export interface DuolingoStreakDataV2 {
|
|
115
|
+
currentStreak: DuolingoStreakInfo | null;
|
|
116
|
+
previousStreak: DuolingoStreakInfo | null;
|
|
117
|
+
longestStreak?: DuolingoStreakInfo;
|
|
118
|
+
updatedTimestamp?: number;
|
|
119
|
+
[key: string]: unknown;
|
|
120
|
+
}
|
|
121
|
+
/** User data from the 2023-05-23 API — includes non-language courses. */
|
|
122
|
+
export interface DuolingoUserDataV2 {
|
|
123
|
+
id: number;
|
|
124
|
+
username: string;
|
|
125
|
+
name: string | null;
|
|
126
|
+
picture: string;
|
|
127
|
+
totalXp: number;
|
|
128
|
+
streak: number;
|
|
129
|
+
streakData: DuolingoStreakDataV2;
|
|
130
|
+
courses: DuolingoCourse[];
|
|
131
|
+
hasPlus: boolean;
|
|
132
|
+
subscriberLevel: string;
|
|
133
|
+
fromLanguage: string;
|
|
134
|
+
learningLanguage: string;
|
|
135
|
+
location?: string | null;
|
|
136
|
+
creationDate?: number;
|
|
137
|
+
[key: string]: unknown;
|
|
138
|
+
}
|
|
139
|
+
export interface DuolingoUserIdResponse {
|
|
140
|
+
users: {
|
|
141
|
+
id: number;
|
|
142
|
+
}[];
|
|
143
|
+
}
|
|
144
|
+
export interface DuolingoShopItem {
|
|
145
|
+
id: string;
|
|
146
|
+
name?: string;
|
|
147
|
+
type: string;
|
|
148
|
+
localizedDescription?: string;
|
|
149
|
+
price: number;
|
|
150
|
+
currencyType: string;
|
|
151
|
+
lastUsedDate?: number;
|
|
152
|
+
lastPurchaseDate?: number;
|
|
153
|
+
isActive?: boolean;
|
|
154
|
+
value?: number;
|
|
155
|
+
[key: string]: unknown;
|
|
156
|
+
}
|
|
157
|
+
export interface DuolingoShopItemsResponse {
|
|
158
|
+
shopItems: DuolingoShopItem[];
|
|
159
|
+
}
|
|
160
|
+
export interface DuolingoHealth {
|
|
161
|
+
eligibleForFreeRefill: boolean;
|
|
162
|
+
healthEnabled: boolean;
|
|
163
|
+
hearts: number;
|
|
164
|
+
maxHearts: number;
|
|
165
|
+
secondsPerHeartSegment: number;
|
|
166
|
+
secondsUntilNextHeartSegment: number | null;
|
|
167
|
+
useHealth: boolean;
|
|
168
|
+
unlimitedHeartsAvailable: boolean;
|
|
169
|
+
}
|
|
170
|
+
export interface DuolingoStreakGoalCheckpoint {
|
|
171
|
+
length: number;
|
|
172
|
+
dayInterval: number;
|
|
173
|
+
tier: number;
|
|
174
|
+
}
|
|
175
|
+
export interface DuolingoStreakGoal {
|
|
176
|
+
userId: string;
|
|
177
|
+
lastCompleteGoal: number;
|
|
178
|
+
checkpoints: DuolingoStreakGoalCheckpoint[];
|
|
179
|
+
nextSelectedGoal?: DuolingoStreakGoalCheckpoint;
|
|
180
|
+
}
|
|
181
|
+
export interface DuolingoStreakGoalCurrentResponse {
|
|
182
|
+
hasActiveGoal: boolean;
|
|
183
|
+
streakGoal: DuolingoStreakGoal | null;
|
|
184
|
+
}
|
|
185
|
+
export interface DuolingoStreakGoalOption {
|
|
186
|
+
length: number;
|
|
187
|
+
dayInterval: number;
|
|
188
|
+
tier: number;
|
|
189
|
+
}
|
|
190
|
+
export interface DuolingoStreakGoalNextOptionsResponse {
|
|
191
|
+
currentStreakOptions: DuolingoStreakGoalOption[];
|
|
192
|
+
previousStreakOptions: DuolingoStreakGoalOption[];
|
|
193
|
+
}
|
|
194
|
+
export interface DuolingoXpGain {
|
|
195
|
+
skillId: string | null;
|
|
196
|
+
xp: number;
|
|
197
|
+
time: number;
|
|
198
|
+
eventType?: string | null;
|
|
199
|
+
}
|
|
200
|
+
export interface DuolingoStreakData {
|
|
201
|
+
updatedTimestamp: number;
|
|
202
|
+
[key: string]: unknown;
|
|
203
|
+
}
|
|
204
|
+
export interface DuolingoDailyProgress {
|
|
205
|
+
xpGoal: number;
|
|
206
|
+
xpGains: DuolingoXpGain[];
|
|
207
|
+
streakData: DuolingoStreakData;
|
|
208
|
+
}
|
|
209
|
+
export interface DuolingoLeaderboardData {
|
|
210
|
+
ranking: Record<string, string>;
|
|
211
|
+
}
|
|
212
|
+
/** A user entry from /2017-06-30/friends/users/{id}/following or /followers */
|
|
213
|
+
export interface DuolingoFriendUser {
|
|
214
|
+
userId: number;
|
|
215
|
+
username: string;
|
|
216
|
+
displayName: string | null;
|
|
217
|
+
picture: string;
|
|
218
|
+
totalXp: number;
|
|
219
|
+
isFollowing: boolean;
|
|
220
|
+
isFollowedBy: boolean;
|
|
221
|
+
hasSubscription: boolean;
|
|
222
|
+
userScore?: {
|
|
223
|
+
courseId: string;
|
|
224
|
+
score: number | null;
|
|
225
|
+
};
|
|
226
|
+
[key: string]: unknown;
|
|
227
|
+
}
|
|
228
|
+
export interface DuolingoFollowingResponse {
|
|
229
|
+
following: {
|
|
230
|
+
users: DuolingoFriendUser[];
|
|
231
|
+
totalUsers: number;
|
|
232
|
+
cursor: string | null;
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
export interface DuolingoFollowersResponse {
|
|
236
|
+
followers: {
|
|
237
|
+
users: DuolingoFriendUser[];
|
|
238
|
+
totalUsers: number;
|
|
239
|
+
cursor: string | null;
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
export interface DuolingoSessionRequest {
|
|
243
|
+
fromLanguage: string;
|
|
244
|
+
learningLanguage: string;
|
|
245
|
+
challengeTypes: string[];
|
|
246
|
+
skillId?: string;
|
|
247
|
+
type: string;
|
|
248
|
+
juicy: boolean;
|
|
249
|
+
smartTipsVersion: number;
|
|
250
|
+
}
|
|
251
|
+
export interface DuolingoChallenge {
|
|
252
|
+
prompt?: string;
|
|
253
|
+
tts?: string;
|
|
254
|
+
metadata?: {
|
|
255
|
+
non_character_tts?: {
|
|
256
|
+
tokens: Record<string, string>;
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
tokens?: DuolingoToken[];
|
|
260
|
+
[key: string]: unknown;
|
|
261
|
+
}
|
|
262
|
+
export type DuolingoToken = {
|
|
263
|
+
tts?: string;
|
|
264
|
+
value?: string;
|
|
265
|
+
[key: string]: unknown;
|
|
266
|
+
} | DuolingoToken[];
|
|
267
|
+
export interface DuolingoSessionResponse {
|
|
268
|
+
challenges: DuolingoChallenge[];
|
|
269
|
+
/** Map of TTS URL → annotation data. Keys are the TTS CDN URLs. */
|
|
270
|
+
ttsAnnotations?: Record<string, unknown>;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wBAAwB,EAAE,MAAM,CAAC;IACjC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,0BAA0B,CAAC;IACjD,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACpD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,cAAc,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,oBAAoB,CAAC;IACjC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,4BAA4B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAC5C,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CACjD;AAED,MAAM,WAAW,iCAAiC;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qCAAqC;IACpD,oBAAoB,EAAE,wBAAwB,EAAE,CAAC;IACjD,qBAAqB,EAAE,wBAAwB,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,UAAU,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE;QACT,KAAK,EAAE,kBAAkB,EAAE,CAAC;QAC5B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE;QACT,KAAK,EAAE,kBAAkB,EAAE,CAAC;QAC5B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE;QACT,iBAAiB,CAAC,EAAE;YAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;SAChC,CAAC;KACH,CAAC;IACF,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACxD,aAAa,EAAE,CAAC;AAEpB,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @udondan/duolingo — public library API
|
|
3
|
+
*
|
|
4
|
+
* Use this entry point when importing the package as a library:
|
|
5
|
+
*
|
|
6
|
+
* import { DuolingoClient } from '@udondan/duolingo';
|
|
7
|
+
*
|
|
8
|
+
* For the MCP server binary, use the `duolingo-mcp` CLI (installed via
|
|
9
|
+
* `npm install -g @udondan/duolingo`) or the `@udondan/duolingo/server` export.
|
|
10
|
+
*/
|
|
11
|
+
export { DuolingoClient, getClient, resetClient } from './client/duolingo.js';
|
|
12
|
+
export { DuolingoClientError, DuolingoAuthError, DuolingoNotFoundError, DuolingoCaptchaError, DuolingoLanguageNotFoundError, } from './client/errors.js';
|
|
13
|
+
export type { DuolingoUserData, DuolingoUserDataV2, DuolingoLanguage, DuolingoLanguageData, DuolingoCalendarEntry, DuolingoSkill, DuolingoTrackingProperties, DuolingoCourse, DuolingoFriendUser, DuolingoFollowingResponse, DuolingoFollowersResponse, DuolingoDailyProgress, DuolingoXpGain, DuolingoStreakData, DuolingoStreakDataV2, DuolingoStreakInfo, DuolingoStreakGoal, DuolingoStreakGoalCheckpoint, DuolingoStreakGoalCurrentResponse, DuolingoStreakGoalNextOptionsResponse, DuolingoStreakGoalOption, DuolingoShopItem, DuolingoHealth, DuolingoLeaderboardData, DuolingoSessionRequest, DuolingoSessionResponse, DuolingoChallenge, DuolingoToken, } from './client/types.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAEV,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,0BAA0B,EAG1B,cAAc,EAGd,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EAGzB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAGlB,oBAAoB,EACpB,kBAAkB,EAGlB,kBAAkB,EAClB,4BAA4B,EAC5B,iCAAiC,EACjC,qCAAqC,EACrC,wBAAwB,EAGxB,gBAAgB,EAGhB,cAAc,EAGd,uBAAuB,EAGvB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,aAAa,GACd,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @udondan/duolingo — public library API
|
|
3
|
+
*
|
|
4
|
+
* Use this entry point when importing the package as a library:
|
|
5
|
+
*
|
|
6
|
+
* import { DuolingoClient } from '@udondan/duolingo';
|
|
7
|
+
*
|
|
8
|
+
* For the MCP server binary, use the `duolingo-mcp` CLI (installed via
|
|
9
|
+
* `npm install -g @udondan/duolingo`) or the `@udondan/duolingo/server` export.
|
|
10
|
+
*/
|
|
11
|
+
// Client class and singleton helpers
|
|
12
|
+
export { DuolingoClient, getClient, resetClient } from './client/duolingo.js';
|
|
13
|
+
// All error classes
|
|
14
|
+
export { DuolingoClientError, DuolingoAuthError, DuolingoNotFoundError, DuolingoCaptchaError, DuolingoLanguageNotFoundError, } from './client/errors.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,qCAAqC;AACrC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9E,oBAAoB;AACpB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Duolingo MCP Server
|
|
4
|
+
*
|
|
5
|
+
* A TypeScript MCP server that exposes Duolingo learning data and actions to
|
|
6
|
+
* LLM agents via the unofficial Duolingo REST API.
|
|
7
|
+
*
|
|
8
|
+
* Authentication:
|
|
9
|
+
* Set the following environment variables before starting the server:
|
|
10
|
+
* - DUOLINGO_USERNAME: Your Duolingo username
|
|
11
|
+
* - DUOLINGO_JWT: Your Duolingo JWT token (extracted from browser)
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* npm run build && npm start
|
|
15
|
+
* # or in development:
|
|
16
|
+
* npx tsx src/server.ts
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Duolingo MCP Server
|
|
4
|
+
*
|
|
5
|
+
* A TypeScript MCP server that exposes Duolingo learning data and actions to
|
|
6
|
+
* LLM agents via the unofficial Duolingo REST API.
|
|
7
|
+
*
|
|
8
|
+
* Authentication:
|
|
9
|
+
* Set the following environment variables before starting the server:
|
|
10
|
+
* - DUOLINGO_USERNAME: Your Duolingo username
|
|
11
|
+
* - DUOLINGO_JWT: Your Duolingo JWT token (extracted from browser)
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* npm run build && npm start
|
|
15
|
+
* # or in development:
|
|
16
|
+
* npx tsx src/server.ts
|
|
17
|
+
*/
|
|
18
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
19
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
20
|
+
import { registerAccountTools } from './tools/account.js';
|
|
21
|
+
import { registerLanguageTools } from './tools/language.js';
|
|
22
|
+
import { registerShopTools } from './tools/shop.js';
|
|
23
|
+
const server = new McpServer({
|
|
24
|
+
name: 'duolingo_mcp',
|
|
25
|
+
version: '1.0.0',
|
|
26
|
+
}, {
|
|
27
|
+
instructions: 'This server provides access to Duolingo learning data via the unofficial ' +
|
|
28
|
+
'Duolingo API. You can query user profiles, streak information, language ' +
|
|
29
|
+
'progress, topics, words, TTS audio, and more. ' +
|
|
30
|
+
'Authentication requires DUOLINGO_USERNAME and DUOLINGO_JWT environment variables. ' +
|
|
31
|
+
'To get your JWT token: log in to Duolingo in a browser, open the developer ' +
|
|
32
|
+
'console, and run: ' +
|
|
33
|
+
"document.cookie.match(new RegExp('(^| )jwt_token=([^;]+)'))[0].slice(11)",
|
|
34
|
+
});
|
|
35
|
+
registerAccountTools(server);
|
|
36
|
+
registerLanguageTools(server);
|
|
37
|
+
registerShopTools(server);
|
|
38
|
+
const transport = new StdioServerTransport();
|
|
39
|
+
await server.connect(transport);
|
|
40
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;IACE,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,OAAO;CACjB,EACD;IACE,YAAY,EACV,2EAA2E;QAC3E,0EAA0E;QAC1E,gDAAgD;QAChD,oFAAoF;QACpF,6EAA6E;QAC7E,oBAAoB;QACpB,0EAA0E;CAC7E,CACF,CAAC;AAEF,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE1B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account-level Duolingo MCP tools.
|
|
3
|
+
*
|
|
4
|
+
* Tools: get_user_info, get_settings, get_streak_info, get_daily_xp_progress,
|
|
5
|
+
* get_languages, get_courses, get_friends, get_calendar, get_leaderboard,
|
|
6
|
+
* get_shop_items, get_health, get_currencies, get_streak_goal
|
|
7
|
+
*/
|
|
8
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
|
+
export declare function registerAccountTools(server: McpServer): void;
|
|
10
|
+
//# sourceMappingURL=account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/tools/account.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA22B5D"}
|