تنبيه سعر الصرف على تيليجرام

راقب سعر الدولار كل ساعة، وتصلك رسالة على تيليجرام إذا تحرك أكثر من 1%.

سهل توفّر ~2 ساعة شهريًا المالية والإدارةبواسطة فريق Flowngn

تعمل مع n8n · Make · Zapier

كيف تعمل

المشغّل: جدول زمني — كل ساعة
  1. اجلب أحدث أسعار الدولار من واجهة أسعار صرف مجانية.
  2. قارن عملاتك بآخر سعر رآه الـworkflow.
  3. إذا تحركت أي عملة أكثر من 1%، أرسل السعر القديم والجديد ونسبة التغيير على تيليجرام.

المخطط

trueEvery hourSchedule TriggerGet USD ratesHTTP Request{ }Compare with last r…Code⑂Moved 1% or more?IfTAlert on TelegramTelegram
مشغّل تطبيق منطق كود

الكود

كود JavaScript المستخدم في خطوات Code، وهو مضمَّن بالفعل في القالب بالأسفل.

Compare with last rate · عقدة Code
// Compares today's USD rates with the last rates this workflow saw.
// The last rates are kept in workflow static data, which only saves on active (production) runs.
const CURRENCIES = ["EGP", "SAR", "AED"];
const THRESHOLD = 1; // percent

const rates = $input.first().json.rates || {};
const memory = $getWorkflowStaticData("global");
const last = memory.rates || {};

const moves = CURRENCIES
  .filter((c) => rates[c] && last[c])
  .map((c) => ({ currency: c, from: last[c], to: rates[c], change: ((rates[c] - last[c]) / last[c]) * 100 }))
  .filter((m) => Math.abs(m.change) >= THRESHOLD);

// Only move the baseline when we alert, so slow drifts still add up to an alert.
if (!memory.rates || moves.length) memory.rates = Object.fromEntries(CURRENCIES.map((c) => [c, rates[c]]));

return [{
  json: {
    alert: moves.length > 0,
    message: moves
      .map((m) => `USD/${m.currency}: ${m.from.toFixed(2)} → ${m.to.toFixed(2)} (${m.change > 0 ? "+" : ""}${m.change.toFixed(1)}%)`)
      .join("\n"),
  },
}];

ابنِها بأداتك

اختر أداتك — نفس الأتمتة، خطوة بخطوة.

انسخه والصقه مباشرة في مساحة عمل n8n (Ctrl+V)، أو حمّله واستخدم Import from File. بعد ذلك اربط حساباتك واستبدل كل قيمة تبدأ بـ YOUR_.

ملف Workflow JSON
عرض الكود (171 سطر)
{
  "name": "تنبيه سعر الصرف على تيليجرام (Flowngn)",
  "nodes": [
    {
      "parameters": {
        "content": "## تنبيه سعر الصرف على تيليجرام\nراقب سعر الدولار كل ساعة، وتصلك رسالة على تيليجرام إذا تحرك أكثر من 1%.\n\n**Setup**\n1. Open each node and connect your own credentials.\n2. Replace every YOUR_… placeholder.\n3. Test once, then activate.\n\nFree template from Flowngn",
        "height": 260,
        "width": 340
      },
      "id": "22e076db-ed1a-48e3-aaf2-6913115a1802",
      "name": "Setup notes",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -420,
        -60
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 1
            }
          ]
        }
      },
      "id": "22e076db-ed1a-48e3-aaf2-6913115a1802",
      "name": "Every hour",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "url": "https://open.er-api.com/v6/latest/USD",
        "options": {}
      },
      "id": "22e076db-ed1a-48e3-aaf2-6913115a1802",
      "name": "Get USD rates",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        300,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Compares today's USD rates with the last rates this workflow saw.\n// The last rates are kept in workflow static data, which only saves on active (production) runs.\nconst CURRENCIES = [\"EGP\", \"SAR\", \"AED\"];\nconst THRESHOLD = 1; // percent\n\nconst rates = $input.first().json.rates || {};\nconst memory = $getWorkflowStaticData(\"global\");\nconst last = memory.rates || {};\n\nconst moves = CURRENCIES\n  .filter((c) => rates[c] && last[c])\n  .map((c) => ({ currency: c, from: last[c], to: rates[c], change: ((rates[c] - last[c]) / last[c]) * 100 }))\n  .filter((m) => Math.abs(m.change) >= THRESHOLD);\n\n// Only move the baseline when we alert, so slow drifts still add up to an alert.\nif (!memory.rates || moves.length) memory.rates = Object.fromEntries(CURRENCIES.map((c) => [c, rates[c]]));\n\nreturn [{\n  json: {\n    alert: moves.length > 0,\n    message: moves\n      .map((m) => `USD/${m.currency}: ${m.from.toFixed(2)} → ${m.to.toFixed(2)} (${m.change > 0 ? \"+\" : \"\"}${m.change.toFixed(1)}%)`)\n      .join(\"\\n\"),\n  },\n}];"
      },
      "id": "22e076db-ed1a-48e3-aaf2-6913115a1802",
      "name": "Compare with last rate",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.alert }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "22e076db-ed1a-48e3-aaf2-6913115a1802",
      "name": "Moved 1% or more?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        900,
        0
      ]
    },
    {
      "parameters": {
        "chatId": "YOUR_CHAT_ID",
        "text": "=Exchange rate moved:\n{{ $json.message }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "id": "22e076db-ed1a-48e3-aaf2-6913115a1802",
      "name": "Alert on Telegram",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1200,
        0
      ]
    }
  ],
  "connections": {
    "Every hour": {
      "main": [
        [
          {
            "node": "Get USD rates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get USD rates": {
      "main": [
        [
          {
            "node": "Compare with last rate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare with last rate": {
      "main": [
        [
          {
            "node": "Moved 1% or more?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Moved 1% or more?": {
      "main": [
        [
          {
            "node": "Alert on Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}

← افتحها في ساحة التجربة لتعديلها

نصائح

  • آخر سعر يُحفظ داخل الـworkflow نفسه، لذلك يعمل فقط بعد تفعيله (وليس في التشغيل التجريبي اليدوي).
  • الواجهات المجانية تتحدث بضع مرات في اليوم؛ اعتمد على سعر البنك عند التسعير الفعلي.

أتمتات مشابهة