This workflow follows the HTTP Request → Telegram recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "My workflow",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-352,
576
],
"id": "16c122ab-06bc-47bf-9892-a00f48b667dc",
"name": "Schedule Trigger"
},
{
"parameters": {
"jsCode": "// \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 XML \u0432 JSON (\u0440\u0443\u0447\u043d\u043e\u0439 \u043f\u0430\u0440\u0441\u0435\u0440)\nfunction parseXMLToJSON(xmlText) {\n const result = {\n items: []\n };\n \n try {\n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0432\u0441\u0435 item'\u044b \u0438\u0437 XML\n const itemRegex = /<item>([\\s\\S]*?)<\\/item>/g;\n const items = [];\n let match;\n \n while ((match = itemRegex.exec(xmlText)) !== null) {\n items.push(match[1]);\n }\n \n // \u041f\u0430\u0440\u0441\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 item\n for (const itemXml of items) {\n const item = {};\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c title\n const titleMatch = itemXml.match(/<title>([\\s\\S]*?)<\\/title>/);\n if (titleMatch) item.title = titleMatch[1].replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim();\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c description\n const descMatch = itemXml.match(/<description>([\\s\\S]*?)<\\/description>/);\n if (descMatch) item.description = descMatch[1].replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim();\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c author\n const authorMatch = itemXml.match(/<author>([\\s\\S]*?)<\\/author>/);\n if (authorMatch) item.author = authorMatch[1].replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim();\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c link\n const linkMatch = itemXml.match(/<link>([\\s\\S]*?)<\\/link>/);\n if (linkMatch) item.link = linkMatch[1].trim();\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c guid (\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID)\n const guidMatch = itemXml.match(/<guid>([\\s\\S]*?)<\\/guid>/);\n if (guidMatch) item.id = guidMatch[1].trim();\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c pubDate\n const dateMatch = itemXml.match(/<pubDate>([\\s\\S]*?)<\\/pubDate>/);\n if (dateMatch) item.pubDate = dateMatch[1].trim();\n \n // \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0433\u043e\u0440\u043e\u0434 \u0438\u0437 title \u0438\u043b\u0438 description\n const cityMatch = item.title?.match(/\\((.*?)\\)/) || item.description?.match(/\\((.*?)\\)/);\n if (cityMatch) item.city = cityMatch[1];\n \n // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\n item.content = (item.title || '') + ' ' + (item.description || '');\n \n result.items.push(item);\n }\n } catch (e) {\n console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 XML:', e);\n }\n \n return result;\n}\n\n// \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435\nconst inputData = $input.all();\n\n// \u0417\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\nlet allVacancies = [];\n\n// \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\nfor (const item of inputData) {\n // \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c XML \u0442\u0435\u043a\u0441\u0442 \u0438\u0437 \u043f\u043e\u043b\u044f data\n const xmlText = item.json.data;\n \n if (xmlText && typeof xmlText === 'string') {\n // \u041f\u0430\u0440\u0441\u0438\u043c XML \u0432 JSON\n const parsed = parseXMLToJSON(xmlText);\n allVacancies = allVacancies.concat(parsed.items);\n }\n}\n\n// \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442, \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 n8n\nreturn allVacancies.map(vacancy => ({ json: vacancy }));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
240,
0
],
"id": "c667156b-ec24-434f-b717-a6f1be0f0d39",
"name": "Code in JavaScript"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "27324b60-597a-4281-84f4-106a317f6672",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0431\u0435\u0437 \u043e\u043f\u044b\u0442\u0430",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "0e08c5ff-207d-459e-ab6d-f65ccfd4c61c",
"leftValue": "={{ $json.content }}",
"rightValue": "\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "641bea01-d7b5-41ac-a359-f61e0b6e2256",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0441\u0442\u0430\u0436\u0435\u0440 project",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "0697eb7b-f966-401c-94ba-8ddfb97b75e1",
"leftValue": "={{ $json.content }}",
"rightValue": "\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "5b49fdcd-00a4-4770-b455-9f0856091ea1",
"leftValue": "={{ $json.content }}",
"rightValue": "project manager",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "a8115d79-3cd1-4094-a85c-5f2dc5889705",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"options": {
"ignoreCase": true
}
},
"type": "n8n-nodes-base.filter",
"typeVersion": 2.2,
"position": [
480,
0
],
"id": "7d75b306-a838-4dd9-b837-9c1ec6f3ecfb",
"name": "Filter \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b"
},
{
"parameters": {
"maxItems": 5
},
"type": "n8n-nodes-base.limit",
"typeVersion": 1,
"position": [
400,
448
],
"id": "23d6451d-0799-437f-9e55-3f7282aa4a53",
"name": "Limit"
},
{
"parameters": {
"chatId": "673215399",
"text": "={{ $json.message }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
816,
448
],
"id": "ec3df12a-00a9-41ca-903b-378d3d23e7bd",
"name": "Send a text message",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043f\u0435\u0446\u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 MarkdownV2\nfunction escapeMarkdown(text) {\n if (!text) return '';\n \n // \u0421\u0438\u043c\u0432\u043e\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 MarkdownV2\n const specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];\n \n let escaped = String(text);\n for (const char of specialChars) {\n escaped = escaped.replace(new RegExp('\\\\' + char, 'g'), '\\\\' + char);\n }\n \n return escaped;\n}\n\n// \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438\nconst items = $input.all();\n\n// \u0415\u0441\u043b\u0438 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \u043d\u0435\u0442, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\nif (items.length === 0) {\n return [{\n json: {\n message: \"\ud83d\ude14 \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u041f\u0440\u043e\u0432\u0435\u0440\u044e \u0437\u0430\u0432\u0442\u0440\u0430!\"\n }\n }];\n}\n\n// \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\nlet messageText = \"\ud83d\ude80 *\u0414\u0430\u0439\u0434\u0436\u0435\u0441\u0442 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \" + new Date().toLocaleDateString('ru-RU') + \"*\\n\\n\";\n\n// \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u0430\u0436\u0434\u0443\u044e \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044e \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\nfor (let i = 0; i < items.length; i++) {\n const item = items[i].json;\n \n // \u042d\u043a\u0440\u0430\u043d\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f\n const title = escapeMarkdown(item.title || '\u0411\u0435\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f');\n const author = escapeMarkdown(item.author || '\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430');\n let description = escapeMarkdown(item.content || item.description || '');\n \n // \u041e\u0431\u0440\u0435\u0437\u0430\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\n description = description.replace(/\\n/g, ' ').substring(0, 200);\n if (description.length === 200) description += '...';\n \n // \u041d\u043e\u043c\u0435\u0440 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438\n messageText += `*${i + 1}. ${title}*\\n`;\n messageText += `\ud83c\udfe2 ${author}\\n`;\n messageText += `\u2b50 \u0420\u0435\u0439\u0442\u0438\u043d\u0433: ${item.rating || 0}\\n`;\n \n // \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\n messageText += `\ud83d\udcdd ${description}\\n`;\n \n // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\n if (item.source === 'hh.ru') {\n messageText += `\ud83d\udccc \u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: HeadHunter\\n`;\n } else {\n messageText += `\ud83d\udccc \u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: \u0425\u0430\u0431\u0440 \u041a\u0430\u0440\u044c\u0435\u0440\u0430\\n`;\n }\n \n // \u0421\u0441\u044b\u043b\u043a\u0430 (\u043d\u0435 \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u0443\u0435\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435)\n const link = item.link || '';\n messageText += `\ud83d\udd17 [\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438](${link})\\n`;\n \n // \u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c \u043c\u0435\u0436\u0434\u0443 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044f\u043c\u0438 (\u043a\u0440\u043e\u043c\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439)\n if (i < items.length - 1) {\n messageText += `\\n---\\n\\n`;\n }\n}\n\n// \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0434\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\nreturn [{\n json: {\n message: messageText\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
608,
448
],
"id": "bd7303ec-d4ea-4e79-a9b8-b5d12c92093a",
"name": "Code in JavaScript2"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "5aac1461-34f4-4dce-b2c5-72950ff0a2b6",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "641bea01-d7b5-41ac-a359-f61e0b6e2256",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0433\u0438\u0431\u0440\u0438\u0434",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "606c001a-19cb-4222-93fc-60cb3d392a58",
"leftValue": "={{ $json.content }}",
"rightValue": "\u041c\u043e\u0441\u043a\u0432\u0430",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"options": {
"ignoreCase": true
}
},
"type": "n8n-nodes-base.filter",
"typeVersion": 2.2,
"position": [
640,
0
],
"id": "039b2d8c-c7d8-46ec-b245-813adfe6228a",
"name": "Filter \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b"
},
{
"parameters": {
"url": "https://api.hh.ru/vacancies",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "text",
"value": "project manager \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0441\u0442\u0430\u0436\u0435\u0440 \u043c\u043b\u0430\u0434\u0448\u0438\u0439 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442"
},
{
"name": "area",
"value": "1"
},
{
"name": "experience",
"value": "noExperience"
},
{
"name": "employment",
"value": "full"
},
{
"name": "schedule",
"value": "remote"
},
{
"name": "per_page",
"value": "20"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
-64,
1120
],
"id": "d39db29a-9ba8-4447-8871-1d5da72791d2",
"name": "HTTP Request2"
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst result = [];\n\nfor (const item of items) {\n const data = item.json;\n \n // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438\n if (data.items && Array.isArray(data.items)) {\n for (const vacancy of data.items) {\n // \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u0432 \u0442\u043e\u043c \u0436\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u0447\u0442\u043e \u0438 \u043e\u0442 \u0425\u0430\u0431\u0440\u0430\n result.push({\n json: {\n title: vacancy.name,\n description: vacancy.snippet?.requirement || vacancy.snippet?.responsibility || '',\n author: vacancy.employer?.name || '\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430',\n link: vacancy.alternate_url,\n id: vacancy.id,\n city: vacancy.area?.name || '',\n salary: vacancy.salary ? `${vacancy.salary.from || ''} ${vacancy.salary.to || ''} ${vacancy.salary.currency || ''}`.trim() : '\u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430',\n content: (vacancy.name + ' ' + (vacancy.snippet?.requirement || '') + ' ' + (vacancy.snippet?.responsibility || '')).toLowerCase(),\n source: 'hh.ru'\n }\n });\n }\n }\n}\n\nreturn result;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
688
],
"id": "f6d18436-080c-4e8c-9c4f-b516c18adbd5",
"name": "Code in JavaScript3"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "27324b60-597a-4281-84f4-106a317f6672",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0431\u0435\u0437 \u043e\u043f\u044b\u0442\u0430",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "0e08c5ff-207d-459e-ab6d-f65ccfd4c61c",
"leftValue": "={{ $json.content }}",
"rightValue": "\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "641bea01-d7b5-41ac-a359-f61e0b6e2256",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0441\u0442\u0430\u0436\u0435\u0440 project",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "0697eb7b-f966-401c-94ba-8ddfb97b75e1",
"leftValue": "={{ $json.content }}",
"rightValue": "\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "5b49fdcd-00a4-4770-b455-9f0856091ea1",
"leftValue": "={{ $json.content }}",
"rightValue": "project manager",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "a8115d79-3cd1-4094-a85c-5f2dc5889705",
"leftValue": "={{ $json.content }}",
"rightValue": "\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "or"
},
"options": {
"ignoreCase": true
}
},
"type": "n8n-nodes-base.filter",
"typeVersion": 2.2,
"position": [
448,
688
],
"id": "579ef25d-d647-4278-bdb8-fb1d54b368d8",
"name": "Filter \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b1"
},
{
"parameters": {
"jsCode": "// \u041a\u043e\u0434 \u0434\u043b\u044f Node \"Code\"\nconst items = $input.all();\nconst newItems = [];\n\n// \u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0434\u043b\u044f \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0447\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435, \u0442\u0435\u043c \u043b\u0443\u0447\u0448\u0435)\nconst keywords = [\n '\u0438\u0438', '\u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442', '\u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442', 'gpt', // AI\n 'no-code', 'nocode', 'low-code', // No-code\n '\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446', '\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446', '\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442', // \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f\n '\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d', 'project', 'pm', 'agile', 'scrum', '\u043a\u0430\u043d\u0431\u0430\u043d', // \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\n '\u0441\u0442\u0430\u0436\u0435\u0440', '\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a', '\u043c\u043b\u0430\u0434\u0448\u0438\u0439', 'junior', 'trainee' // \u0414\u0443\u0431\u043b\u0435\u0440\u044b \u043f\u043e\u0437\u0438\u0446\u0438\u0438\n];\n\nfor (const item of items) {\n let rating = 0;\n const content = item.json.content ? item.json.content.toLowerCase() : '';\n const title = item.json.title ? item.json.title.toLowerCase() : '';\n\n // \u0418\u0449\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438\n for (const word of keywords) {\n // \u0414\u0430\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0431\u0430\u043b\u043b\u043e\u0432 \u0437\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438\n if (title.includes(word)) {\n rating += 3;\n } else if (content.includes(word)) {\n rating += 1;\n }\n }\n\n // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0439\u0442\u0438\u043d\u0433 \u0432 \u0434\u0430\u043d\u043d\u044b\u0435\n newItems.push({\n json: {\n ...item.json,\n rating: rating // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u0435 \u0441 \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u043e\u043c\n }\n });\n}\n\n// \u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0430 (\u043e\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043a \u043c\u0435\u043d\u044c\u0448\u0438\u043c)\nnewItems.sort((a, b) => b.json.rating - a.json.rating);\n\nreturn newItems;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
432,
1136
],
"id": "c3262969-939b-40c4-8d25-80dbcdf4dd6c",
"name": "Code in JavaScript \u0420\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435"
},
{
"parameters": {},
"type": "n8n-nodes-base.merge",
"typeVersion": 3.2,
"position": [
-16,
448
],
"id": "14a00ec7-7b23-4f5d-8c06-c62f0e1a459c",
"name": "Merge"
},
{
"parameters": {
"jsCode": "// \u041a\u043e\u0434 \u0434\u043b\u044f \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 hh.ru\nconst items = $input.all();\nconst newItems = [];\n\n// \u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0434\u043b\u044f \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0442\u0435 \u0436\u0435, \u0447\u0442\u043e \u0438 \u0434\u043b\u044f \u0425\u0430\u0431\u0440\u0430)\nconst keywords = [\n '\u0438\u0438', '\u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442', '\u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442', 'gpt', // AI\n 'no-code', 'nocode', 'low-code', // No-code\n '\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446', '\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446', '\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442', // \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f\n '\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d', 'project', 'pm', 'agile', 'scrum', '\u043a\u0430\u043d\u0431\u0430\u043d', // \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\n '\u0441\u0442\u0430\u0436\u0435\u0440', '\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a', '\u043c\u043b\u0430\u0434\u0448\u0438\u0439', 'junior', 'trainee', '\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442' // \u0414\u0443\u0431\u043b\u0435\u0440\u044b \u043f\u043e\u0437\u0438\u0446\u0438\u0438\n];\n\nfor (const item of items) {\n let rating = 0;\n \n // \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 item.json (\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 hh.ru)\n const title = item.json.title ? item.json.title.toLowerCase() : '';\n const description = item.json.description ? item.json.description.toLowerCase() : '';\n const content = (title + ' ' + description).toLowerCase();\n \n // \u0418\u0449\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438\n for (const word of keywords) {\n // \u0414\u0430\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0431\u0430\u043b\u043b\u043e\u0432 \u0437\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438\n if (title.includes(word)) {\n rating += 3;\n } \n // \u0418\u0449\u0435\u043c \u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438\n if (description.includes(word)) {\n rating += 1;\n }\n }\n \n // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0440\u0435\u0439\u0442\u0438\u043d\u0433 \u0432 \u0434\u0430\u043d\u043d\u044b\u0435\n newItems.push({\n json: {\n ...item.json,\n rating: rating\n }\n });\n}\n\n// \u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0430\nnewItems.sort((a, b) => b.json.rating - a.json.rating);\n\nreturn newItems;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
208,
1136
],
"id": "342a7575-b8f1-4c4d-9cd5-7e9e2d9f26ac",
"name": "Code in JavaScript \u0420\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u04351"
},
{
"parameters": {
"jsCode": "// \u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439\nconst items = $input.all();\nconst newItems = [];\n\nconst keywords = [\n '\u0438\u0438', '\u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442', '\u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442', 'gpt',\n 'no-code', 'nocode', 'low-code',\n '\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446', '\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446', '\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442',\n '\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d', 'project', 'pm', 'agile', 'scrum', '\u043a\u0430\u043d\u0431\u0430\u043d',\n '\u0441\u0442\u0430\u0436\u0435\u0440', '\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a', '\u043c\u043b\u0430\u0434\u0448\u0438\u0439', 'junior', 'trainee', '\u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442'\n];\n\nfor (const item of items) {\n let rating = 0;\n \n // \u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430\n let fullText = '';\n \n // \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 content (\u043a\u0430\u043a \u0443 \u0425\u0430\u0431\u0440\u0430)\n if (item.json.content) {\n fullText = item.json.content.toLowerCase();\n } \n // \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c title \u0438 description (\u043a\u0430\u043a \u0443 hh.ru)\n else {\n const title = item.json.title ? item.json.title.toLowerCase() : '';\n const description = item.json.description ? item.json.description.toLowerCase() : '';\n fullText = title + ' ' + description;\n }\n \n // \u0410\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043a\u0441\u0442\n for (const word of keywords) {\n if (fullText.includes(word)) {\n // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0441\u043b\u043e\u0432\u043e \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 (\u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u043e\u043d\u0443\u0441)\n const title = item.json.title ? item.json.title.toLowerCase() : '';\n if (title.includes(word)) {\n rating += 3;\n } else {\n rating += 1;\n }\n }\n }\n \n newItems.push({\n json: {\n ...item.json,\n rating: rating\n }\n });\n}\n\nnewItems.sort((a, b) => b.json.rating - a.json.rating);\n\nreturn newItems;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
192,
448
],
"id": "d0a9c11b-7ef2-414b-bd5d-cbc62eb449a7",
"name": "Code in JavaScript \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435"
},
{
"parameters": {
"url": "https://career.habr.com/vacancies/rss",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "project manager \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043c\u043b\u0430\u0434\u0448\u0438\u0439 \u0441\u0442\u0430\u0436\u0435\u0440"
}
]
},
"options": {
"batching": {
"batch": {
"batchSize": 1
}
},
"response": {
"response": {
"responseFormat": "text"
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
0,
0
],
"id": "394653bc-df34-47ae-9e1e-a9c21f0664e3",
"name": "HTTP Request \u0425\u0430\u0431\u0440",
"notesInFlow": false
},
{
"parameters": {
"url": "https://api.hh.ru/vacancies",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "text",
"value": "project manager \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0441\u0442\u0430\u0436\u0435\u0440 \u043c\u043b\u0430\u0434\u0448\u0438\u0439 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
0,
688
],
"id": "a85dffbf-06f2-471a-b5f9-e7c72a7f4630",
"name": "HTTP Request3 hh"
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "HTTP Request \u0425\u0430\u0431\u0440",
"type": "main",
"index": 0
},
{
"node": "HTTP Request3 hh",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Filter \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b",
"type": "main",
"index": 0
}
]
]
},
"Filter \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b": {
"main": [
[
{
"node": "Filter \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b",
"type": "main",
"index": 0
}
]
]
},
"Limit": {
"main": [
[
{
"node": "Code in JavaScript2",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript2": {
"main": [
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
},
"Filter \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript3": {
"main": [
[
{
"node": "Filter \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b1",
"type": "main",
"index": 0
}
]
]
},
"Filter \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b1": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Code in JavaScript \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435": {
"main": [
[
{
"node": "Limit",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request \u0425\u0430\u0431\u0440": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request3 hh": {
"main": [
[
{
"node": "Code in JavaScript3",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"versionId": "4313b520-1d2d-47ea-ab3b-d41c68282c69",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "l9L86XsLUiDhqhlY",
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
telegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
V2.0 Career-Bot-Workflow. Uses telegram, httpRequest. Scheduled trigger; 16 nodes.
Source: https://github.com/Gitman404/job-search-assistant/blob/18cd35fb5b2712c55c54bb1472c37eb48a6be5dc/v2-n8n/workflow/v2.0_career-bot-workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
V2.1 Career-Bot-Workflow. Uses telegram, httpRequest, readWriteFile, googleDrive. Scheduled trigger; 33 nodes.
v2.2_career-bot-workflow. Uses telegram, httpRequest, googleDrive, googleSheets. Scheduled trigger; 27 nodes.
How it works: Schedule Trigger on a daily basis (configured at 7.30 am) Connects Google Contacts to get personal information from them Field Checker on birthday date & firstnames. And see if there is
career-bot-workflow. Uses telegram, httpRequest, googleDrive, googleSheets. Scheduled trigger; 25 nodes.
Get notified when the International Space Station passes over your location - but only when you can actually see it! This workflow combines real-time ISS tracking with weather condition checks to send