{
  "name": "Kwork \u2014 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432",
  "nodes": [
    {
      "parameters": {},
      "id": "8c62a006-1dae-44f7-9574-057359c9aae8",
      "name": "\u0417\u0430\u043f\u0443\u0441\u043a \u0432\u0440\u0443\u0447\u043d\u0443\u044e",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        16,
        592
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "login",
              "name": "login",
              "value": "={{ $env.KWORK_LOGIN }}",
              "type": "string"
            },
            {
              "id": "password",
              "name": "password",
              "value": "={{ $env.KWORK_PASSWORD }}",
              "type": "string"
            },
            {
              "id": "categories",
              "name": "categories",
              "value": "={{ $env.KWORK_CATEGORIES || \"37,38,41\" }}",
              "type": "string"
            },
            {
              "id": "price_from",
              "name": "price_from",
              "value": "={{ $env.KWORK_PRICE_FROM || \"10000\" }}",
              "type": "string"
            },
            {
              "id": "price_to",
              "name": "price_to",
              "value": "={{ $env.KWORK_PRICE_TO || \"\" }}",
              "type": "string"
            },
            {
              "id": "hiring_from",
              "name": "hiring_from",
              "value": "={{ $env.KWORK_HIRING_FROM || \"\" }}",
              "type": "string"
            },
            {
              "id": "max_offers",
              "name": "max_offers",
              "value": "={{ $env.KWORK_MAX_OFFERS || \"5\" }}",
              "type": "string"
            },
            {
              "id": "page",
              "name": "page",
              "value": "={{ $env.KWORK_PAGE || \"1\" }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "7c1ce8d1-d5d4-4240-951a-e3ec1fff3824",
      "name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        240,
        368
      ],
      "notesInFlow": true,
      "notes": "\u0421\u0435\u043a\u0440\u0435\u0442\u044b \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438\u0437 $env. \u041f\u0440\u0438\u043c\u0435\u0440: kwork-monitoring.env.example"
    },
    {
      "parameters": {
        "operation": "select",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "kwork_tokens",
          "mode": "list",
          "cachedResultName": "kwork_tokens"
        },
        "returnAll": true,
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        480,
        368
      ],
      "id": "969a9cc9-d9c0-4702-adb8-f6e9b7a01e22",
      "name": "\u0422\u043e\u043a\u0435\u043d \u0438\u0437 \u0411\u0414",
      "notesInFlow": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "notes": "\u0427\u0438\u0442\u0430\u0435\u0442 kwork_tokens.\n0 \u0441\u0442\u0440\u043e\u043a \u2014 \u043f\u043e\u0439\u0434\u0451\u043c \u043d\u0430 signIn."
    },
    {
      "parameters": {
        "jsCode": "// \u0412\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d item \u043d\u0430 \u0432\u044b\u0445\u043e\u0434: { token, valid, expires_at }\nconst BUFFER_MS = 60_000; // \u0437\u0430\u043f\u0430\u0441 1 \u043c\u0438\u043d \u0434\u043e \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f\nconst rows = $input.all();\n\nif (!rows.length) {\n  return [{ json: { token: null, valid: false, expires_at: null, source: 'db_empty' } }];\n}\n\nconst latest = rows.reduce((best, item) => {\n  const a = new Date(best.json.expires_at).getTime();\n  const b = new Date(item.json.expires_at).getTime();\n  return b > a ? item : best;\n}, rows[0]);\n\nconst token = latest.json.token;\nconst expiresAt = latest.json.expires_at;\nconst valid = Boolean(token) && new Date(expiresAt).getTime() > Date.now() + BUFFER_MS;\n\nreturn [{\n  json: {\n    token,\n    valid,\n    expires_at: expiresAt,\n    source: 'db',\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        368
      ],
      "id": "5825b455-e7a2-4596-bd4a-4c52b1594d29",
      "name": "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 \u0411\u0414",
      "notesInFlow": true,
      "notes": "\u0411\u0435\u0440\u0451\u0442 \u0441\u0430\u043c\u044b\u0439 \u0441\u0432\u0435\u0436\u0438\u0439 expires_at.\nvalid=true \u2192 \u043a\u044d\u0448, \u0438\u043d\u0430\u0447\u0435 signIn."
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "token-valid",
              "leftValue": "={{ $json.valid }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        960,
        368
      ],
      "id": "75328b93-481a-44cc-8880-3225ad242fd4",
      "name": "\u0422\u043e\u043a\u0435\u043d \u0435\u0449\u0451 \u0436\u0438\u0432?",
      "notesInFlow": true,
      "notes": "true \u2192 \u043a\u044d\u0448\false \u2192 signIn"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.kwork.ru/signIn",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ 'Basic ' + $env.KWORK_API_BASIC }}"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "login",
              "value": "={{ $('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.login }}"
            },
            {
              "name": "password",
              "value": "={{ $('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.password }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {}
          },
          "proxy": "={{ $env.KWORK_HTTP_PROXY || $env.http_proxy || \"\" }}"
        }
      },
      "id": "da3f3c48-d82d-4df1-b31a-121bc73f97b3",
      "name": "Kwork: \u0432\u0445\u043e\u0434",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1200,
        560
      ],
      "notesInFlow": true,
      "notes": "\u0422\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0432 \u0411\u0414 \u043f\u0440\u043e\u0442\u0443\u0445.\n\u041b\u043e\u0433\u0438\u043d \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0437 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438."
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst token = data.response?.token;\n\nif (!token) {\n  throw new Error('signIn \u043d\u0435 \u0432\u0435\u0440\u043d\u0443\u043b token: ' + JSON.stringify(data));\n}\n\nconst expiredSec = Number(data.response?.expired ?? 86400);\nconst expiresAt = new Date(Date.now() + expiredSec * 1000).toISOString();\n\n// \u0415\u0434\u0438\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u043b\u044f Kwork: \u043f\u0440\u043e\u0435\u043a\u0442\u044b (\u043a\u0430\u043a \u0441 \u0432\u0435\u0442\u043a\u0438 \u0411\u0414)\nreturn [{\n  json: {\n    token,\n    valid: true,\n    expires_at: expiresAt,\n    source: 'signIn',\n  },\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1440,
        560
      ],
      "id": "14198ed1-db3d-40cc-932b-1829d75476f8",
      "name": "\u0422\u043e\u043a\u0435\u043d \u0438\u0437 signIn",
      "notesInFlow": true,
      "notes": "response.token \u2192 json.token\n\u041e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441 \u0411\u0414-\u0432\u0435\u0442\u043a\u043e\u0439."
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "kwork_tokens",
          "mode": "list",
          "cachedResultName": "kwork_tokens"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "token": "={{ $json.token }}",
            "expires_at": "={{ $json.expires_at }}",
            "created_at": "={{ $now }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "token",
              "displayName": "token",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "user_id",
              "displayName": "user_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true
            },
            {
              "id": "expires_at",
              "displayName": "expires_at",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1712,
        672
      ],
      "id": "548bd45c-cb1a-44b7-8490-05be32dbed41",
      "name": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0432 \u0411\u0414",
      "notesInFlow": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "notes": "\u041f\u043e\u0431\u043e\u0447\u043d\u0430\u044f \u0432\u0435\u0442\u043a\u0430 \u2014 \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u044b."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ 'https://api.kwork.ru/projects?token=' + encodeURIComponent($json.token) + '&categories=' + encodeURIComponent($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.categories) + ($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.price_from ? '&price_from=' + encodeURIComponent($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.price_from) : '') + ($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.price_to ? '&price_to=' + encodeURIComponent($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.price_to) : '') + ($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.hiring_from ? '&hiring_from=' + encodeURIComponent($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.hiring_from) : '') + ($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.page ? '&page=' + encodeURIComponent($('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').item.json.page) : '') }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ 'Basic ' + $env.KWORK_API_BASIC }}"
            }
          ]
        },
        "options": {
          "proxy": "={{ $env.KWORK_HTTP_PROXY || $env.http_proxy || \"\" }}"
        }
      },
      "id": "60af1f9d-99c4-49f6-9567-38ae8949cd3f",
      "name": "Kwork: \u043f\u0440\u043e\u0435\u043a\u0442\u044b",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1680,
        352
      ],
      "notesInFlow": true,
      "notes": "\u0412\u0441\u0435\u0433\u0434\u0430 $json.token \u2014 \u0438\u0437 \u0411\u0414 \u0438\u043b\u0438 signIn.\n\u0424\u0438\u043b\u044c\u0442\u0440\u044b \u0438\u0437 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438."
    },
    {
      "parameters": {
        "fieldToSplitOut": "response",
        "options": {}
      },
      "id": "bdc3babf-462e-4621-858a-cb7cf7c0edeb",
      "name": "\u041f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        1952,
        352
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nif (!staticData.seenProjectIds) {\n  staticData.seenProjectIds = {};\n}\n\nconst cfg = $('\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438').first().json;\nconst priceFrom = cfg.price_from ? Number(cfg.price_from) : null;\nconst priceTo = cfg.price_to ? Number(cfg.price_to) : null;\nconst maxOffers = cfg.max_offers ? Number(cfg.max_offers) : null;\nconst hiringFrom = cfg.hiring_from ? Number(cfg.hiring_from) : null;\n\nconst out = [];\n\nfor (const item of $input.all()) {\n  const p = item.json;\n  const id = p.id;\n  if (!id) continue;\n\n  if (priceFrom !== null && (p.price ?? 0) < priceFrom) continue;\n  if (priceTo !== null && (p.price ?? 0) > priceTo) continue;\n  //if (maxOffers !== null && (p.offers ?? 999) > maxOffers) continue;\n  if (hiringFrom !== null && (p.user_hired_percent ?? 0) < hiringFrom) continue;\n\n  if (staticData.seenProjectIds[id]) continue;\n  staticData.seenProjectIds[id] = Date.now();\n\n  out.push({\n    json: {\n      id: p.id,\n      title: p.title,\n      price: p.price,\n      offers: p.offers,\n      username: p.username,\n      user_hired_percent: p.user_hired_percent,\n      category_id: p.category_id,\n      time_left: p.time_left,\n      url: `https://kwork.ru/projects/${p.id}`,\n      description_preview: (p.description || '').slice(0, 200),\n      state: p.achievements_list,\n      possible: p.possible_price_limit\n    },\n  });\n}\n\nreturn out;"
      },
      "id": "0e234404-ccab-43fa-8138-5cb776f687c3",
      "name": "\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2176,
        352
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "has-items",
              "leftValue": "={{ $input.all().length }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2f30a87b-506a-43ce-8af2-3914ee14f8ef",
      "name": "\u0415\u0441\u0442\u044c \u043d\u043e\u0432\u044b\u0435?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        2384,
        336
      ]
    },
    {
      "parameters": {
        "content": "## \u041f\u043e\u0442\u043e\u043a \u0442\u043e\u043a\u0435\u043d\u0430\n\n```\n\u0422\u0440\u0438\u0433\u0433\u0435\u0440 \u2192 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u2192 \u0411\u0414 \u2192 \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u2192 IF\n  \u251c\u2500 true  \u2192 Kwork: \u043f\u0440\u043e\u0435\u043a\u0442\u044b  ($json.token)\n  \u2514\u2500 false \u2192 signIn \u2192 \u0422\u043e\u043a\u0435\u043d \u0438\u0437 signIn \u2192 \u043f\u0440\u043e\u0435\u043a\u0442\u044b\n                      \u2514\u2192 \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0411\u0414 (\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e)\n```\n\n\u041e\u0431\u0435 \u0432\u0435\u0442\u043a\u0438 \u043e\u0442\u0434\u0430\u044e\u0442 **\u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0439** item: `{ token, valid, expires_at }`.",
        "height": 280,
        "width": 480,
        "color": 5
      },
      "id": "c8ef456c-8060-4f43-a38d-e337e6130c01",
      "name": "\u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        528,
        -144
      ]
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "marketplace_listings",
          "mode": "list",
          "cachedResultName": "marketplace_listings"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "tg_posted": false,
            "price": "={{ $json.price }}",
            "category_id": "={{ $json.category_id }}",
            "external_id": "={{ $json.id }}",
            "title": "={{ $json.title }}",
            "description": "={{ $json.description_preview }}",
            "url": "={{ $json.url }}",
            "created_at": "={{ $now }}",
            "updated_at": "={{ $now }}",
            "state": "={\"state_json\":{{ JSON.stringify($json.state) }}}",
            "possible": "={{ $json.possible }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "external_id",
              "displayName": "external_id",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "title",
              "displayName": "title",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "description",
              "displayName": "description",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "price",
              "displayName": "price",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "category_id",
              "displayName": "category_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true
            },
            {
              "id": "updated_at",
              "displayName": "updated_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true
            },
            {
              "id": "tg_posted",
              "displayName": "tg_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "boolean",
              "canBeUsedToMatch": true
            },
            {
              "id": "state",
              "displayName": "state",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "object",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "possible",
              "displayName": "possible",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        2672,
        240
      ],
      "id": "4f96c3c0-7382-4d67-9a39-6fcc9c339288",
      "name": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0411\u0414",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "select",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "marketplace_listings",
          "mode": "list",
          "cachedResultName": "marketplace_listings"
        },
        "returnAll": true,
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        624,
        928
      ],
      "id": "2b2fcaa6-6dcb-4f72-a591-dd842bc0e93d",
      "name": "\u041f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u0435\u0437 Telegram",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0434\u043b\u044f Telegram (chat_id \u0438\u0437 $env)\nconst chatId = $env.TELEGRAM_CHAT_ID;\nif (!chatId) {\n  throw new Error('TELEGRAM_CHAT_ID \u043d\u0435 \u0437\u0430\u0434\u0430\u043d \u0432 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 n8n');\n}\n\nconst allProjects = $input.all();\nconst messages = allProjects.map((projectItem) => {\n  const project = projectItem.json;\n  const states = project.state?.state_json || [];\n  const stateStr = states.map((s) => `\ud83c\udfc5 ${s.name} \u2014 ${s.description}`).join('\\n');\n  const desc = (project.description || '').replace(/<br>/g, '\\n');\n  const message = `\n\ud83d\udd39 <b>${project.title}</b>\n\ud83d\udcb0 \u0426\u0435\u043d\u0430: ${project.price} \u0440\u0443\u0431\n\ud83d\udcb0 \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e: ${project.possible} \u0440\u0443\u0431\n\ud83d\udcdd \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435: ${desc}\n\ud83d\udd17 \u0421\u0441\u044b\u043b\u043a\u0430: ${project.url}\n${stateStr ? '\\n\u26a1 \u0421\u0442\u0430\u0442\u0443\u0441\u044b:\\n' + stateStr : ''}\n`;\n  return { json: { chat_id: chatId, text: message.trim(), parse_mode: 'HTML' } };\n});\n\nreturn messages;\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        928
      ],
      "id": "ae8d6153-ad9b-423e-80e5-fd9dee918d95",
      "name": "\u0422\u0435\u043a\u0441\u0442 \u0434\u043b\u044f Telegram"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "9d10accf-3aeb-4290-831d-8a6d9cb903be",
              "leftValue": "={{ $('\u041f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u0435\u0437 Telegram').item.json.tg_posted }}",
              "rightValue": false,
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1008,
        928
      ],
      "id": "0d1b4d21-38c5-4557-b588-9e157cb1821c",
      "name": "\u041d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0432 TG?"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
        "sendHeaders": true,
        "specifyHeaders": "json",
        "jsonHeaders": "{\"Content-Type\": \"application/json\"}",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $env.TELEGRAM_CHAT_ID }}"
            },
            {
              "name": "text",
              "value": "={{ $json.text }}"
            },
            {
              "name": "parse_mode",
              "value": "HTML"
            }
          ]
        },
        "options": {
          "proxy": "={{ $env.KWORK_HTTP_PROXY || $env.http_proxy || \"\" }}"
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1280,
        816
      ],
      "id": "3e2faa58-5d57-4335-b080-eb75b07a4799",
      "name": "Telegram: \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 50
            }
          ]
        }
      },
      "id": "311cdb86-48d1-405d-ac01-1bc6d1568bc0",
      "name": "\u041a\u0430\u0436\u0434\u044b\u0435 50 \u043c\u0438\u043d\u0443\u0442",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        32,
        144
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 5
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        416,
        928
      ],
      "id": "a1ca5dcc-9d08-435a-b691-1a5867d259dd",
      "name": "\u041a\u0430\u0436\u0434\u044b\u0435 5 \u043c\u0438\u043d\u0443\u0442"
    },
    {
      "parameters": {
        "operation": "update",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "marketplace_listings",
          "mode": "list",
          "cachedResultName": "marketplace_listings"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "tg_posted": true,
            "external_id": "={{ $('\u041f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u0435\u0437 Telegram').item.json.external_id }}"
          },
          "matchingColumns": [
            "external_id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "external_id",
              "displayName": "external_id",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "title",
              "displayName": "title",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "description",
              "displayName": "description",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "price",
              "displayName": "price",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "category_id",
              "displayName": "category_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "updated_at",
              "displayName": "updated_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "tg_posted",
              "displayName": "tg_posted",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "boolean",
              "canBeUsedToMatch": true
            },
            {
              "id": "state",
              "displayName": "state",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "object",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1568,
        928
      ],
      "id": "8c055033-fed2-45b3-8eef-fab753654200",
      "name": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c tg_posted",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f n8n\n\n- `KWORK_LOGIN`, `KWORK_PASSWORD`\n- `KWORK_API_BASIC` \u2014 base64 mobile_api:secret (\u0431\u0435\u0437 \u00abBasic \u00bb)\n- `KWORK_HTTP_PROXY` \u0438\u043b\u0438 \u043e\u0431\u0449\u0438\u0439 `http_proxy` (\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e)\n- `KWORK_CATEGORIES`, `KWORK_PRICE_FROM`, \u2026\n- `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`\n\nPostgres: credential **Postgres account** \u0432 UI n8n.",
        "height": 300,
        "width": 480,
        "color": 4
      },
      "id": "env-doc-sticky-kwork-001",
      "name": "Env: \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        16,
        -144
      ]
    }
  ],
  "connections": {
    "\u0417\u0430\u043f\u0443\u0441\u043a \u0432\u0440\u0443\u0447\u043d\u0443\u044e": {
      "main": [
        [
          {
            "node": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438": {
      "main": [
        [
          {
            "node": "\u0422\u043e\u043a\u0435\u043d \u0438\u0437 \u0411\u0414",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0422\u043e\u043a\u0435\u043d \u0438\u0437 \u0411\u0414": {
      "main": [
        [
          {
            "node": "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 \u0411\u0414",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u043e\u043a\u0435\u043d\u0430 \u0411\u0414": {
      "main": [
        [
          {
            "node": "\u0422\u043e\u043a\u0435\u043d \u0435\u0449\u0451 \u0436\u0438\u0432?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0422\u043e\u043a\u0435\u043d \u0435\u0449\u0451 \u0436\u0438\u0432?": {
      "main": [
        [
          {
            "node": "Kwork: \u043f\u0440\u043e\u0435\u043a\u0442\u044b",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Kwork: \u0432\u0445\u043e\u0434",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Kwork: \u0432\u0445\u043e\u0434": {
      "main": [
        [
          {
            "node": "\u0422\u043e\u043a\u0435\u043d \u0438\u0437 signIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0422\u043e\u043a\u0435\u043d \u0438\u0437 signIn": {
      "main": [
        [
          {
            "node": "Kwork: \u043f\u0440\u043e\u0435\u043a\u0442\u044b",
            "type": "main",
            "index": 0
          },
          {
            "node": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0432 \u0411\u0414",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Kwork: \u043f\u0440\u043e\u0435\u043a\u0442\u044b": {
      "main": [
        [
          {
            "node": "\u041f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u041f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443": {
      "main": [
        [
          {
            "node": "\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435": {
      "main": [
        [
          {
            "node": "\u0415\u0441\u0442\u044c \u043d\u043e\u0432\u044b\u0435?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0415\u0441\u0442\u044c \u043d\u043e\u0432\u044b\u0435?": {
      "main": [
        [
          {
            "node": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0411\u0414",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0411\u0414": {
      "main": [
        []
      ]
    },
    "\u041f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u0435\u0437 Telegram": {
      "main": [
        [
          {
            "node": "\u0422\u0435\u043a\u0441\u0442 \u0434\u043b\u044f Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u0422\u0435\u043a\u0441\u0442 \u0434\u043b\u044f Telegram": {
      "main": [
        [
          {
            "node": "\u041d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0432 TG?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u041d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u0432 TG?": {
      "main": [
        [
          {
            "node": "Telegram: \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u041a\u0430\u0436\u0434\u044b\u0435 50 \u043c\u0438\u043d\u0443\u0442": {
      "main": [
        [
          {
            "node": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u041a\u0430\u0436\u0434\u044b\u0435 5 \u043c\u0438\u043d\u0443\u0442": {
      "main": [
        [
          {
            "node": "\u041f\u0440\u043e\u0435\u043a\u0442\u044b \u0431\u0435\u0437 Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram: \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c": {
      "main": [
        [
          {
            "node": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c tg_posted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "48dbcbc6-c2c9-4126-ba4d-83fbe80b1ad2",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "0jJkjDAOcf5YRG4B",
  "tags": []
}