বিডি রেল টিকিট অ্যালার্ম

এক কথায়

এক্সটেনশনটি আসলে একটি টাইমার আর একজন ভদ্র পাহারাদার। টিকিট ছাড়ার ঠিক সেকেন্ড পর্যন্ত অপেক্ষা করে, তারপর টিকিট সাইটকে প্রায় সেকেন্ডে একবার জিজ্ঞেস করে "আমার ট্রেন খুলেছে?" — উত্তর হ্যাঁ হলেই অ্যালার্ম বাজায় আর যে বোতামগুলো চাপতে হবে সেগুলো দেখিয়ে দেয়। নিজে কখনো চাপে না।

এটি মানুষ সাজার চেষ্টা করে না, বট-ধরা ব্যবস্থা থেকে লুকানোরও চেষ্টা করে না। নিরাপদ থাকে কম জিজ্ঞেস করে, অল্প সময়ের জন্য, শুধু দরকারের সময় — আর সাইটের বট-চেক থেকে পুরোপুরি দূরে থেকে।

অংশগুলো

ফাইলকোথায় চলেকাজ
popup.html / popup.jsটুলবারের প্যানেলক্যালেন্ডার, রুট/ট্রেন/সিট ফর্ম, ARM, কাউন্টডাউন, সেভ করা ট্রিপ, ইতিহাস, বাংলা/English।
background.jsসার্ভিস ওয়ার্কার (ব্যাকগ্রাউন্ড)ছাড়ার সময় হিসাব, chrome.alarms বসানো (মূল + ১ দিন + ১ ঘণ্টা আগের রিমাইন্ডার), ~৭৫ সেকেন্ড আগে সাইটের ট্যাব খোলা, নোটিফিকেশন, অ্যালার্মের আওয়াজ চালু/বন্ধ।
content.jseticket.railway.gov.bd পেজের ভেতরেপাহারাদার: লগইন দেখা, ঘড়ি মেলানো, ধীরে খোঁজা, স্ট্যাটাস বক্স, BOOK NOW জ্বালানো, সিট দাগানো, সিট সোজা না উল্টো তার অনুমান।
offscreen.html / offscreen.jsলুকানো এক্সটেনশন পেজসাইরেন বাজায় (Web Audio)।
rail-data.jsসব জায়গায়স্টেশন, ট্রেনের নাম, আর প্রতিটি ট্রেনের ছাড়ার সময় ও জোন (EAST দুপুর ২টা / WEST সকাল ৮টা)।
i18n.jsপ্যানেলবাংলা ও ইংরেজি লেখা।

একটি রানের সময়রেখা

ARM চাপা হলো (প্যানেল)
  └─ ব্যাকগ্রাউন্ড: ছাড়ার দিন = যাত্রার তারিখ − ১০ দিন
     প্রথম খোঁজ = সেদিন সকাল ৮টা (সাধারণ দিনে সব ট্রেন)
     দ্বিতীয় খোঁজ = দুপুর ২টা, শুধু পূর্বাঞ্চলের ট্রেনে (ঈদের সময়ের নিয়ম)
     অ্যালার্ম বসায়:  T−২৪ঘ (রিমাইন্ডার) · T−১ঘ (রিমাইন্ডার) · T−৭৫সে (শুরু), T = প্রথম খোঁজ
     প্রথম খোঁজ শুরু → দ্বিতীয়টার অ্যালার্ম বসে; সিট পেলে → দ্বিতীয়টা বাতিল

T−৭৫সে  ব্যাকগ্রাউন্ড eticket.railway.gov.bd ট্যাব খোলে (বা আগেরটা নেয়), একটি "mission" সেভ করে
         content.js mission দেখে:
           ১. লগইন আছে?                     না → অ্যালার্ম + নোটিফিকেশন, থামো
           ২. এই রানের সময়ের মধ্যে তারিখ ছাড়বে?   না → থামো (অকারণে খুঁজবে না)
           ৩. একটি ছোট ফাইলের জন্য একটি রিকোয়েস্ট → সার্ভারের Date হেডার থেকে
              ঘড়ির পার্থক্য বের করে (প্রায় ±০.৫ সেকেন্ড)

T−০.৫সে খোঁজা শুরু: GET /bookings/search-trips-v2   (সাইটের Search বোতাম যে কল করে, সেটাই)
           প্রতিবারের মাঝে ৭০০ মিলিসেকেন্ড + এলোমেলো ০–২৫০ মিলিসেকেন্ড  (≈ সেকেন্ডে ১বার)
           429 "খুব ঘন ঘন"  → ২, ৪, ৮, ১৫ সেকেন্ড অপেক্ষা …
           401 "লগআউট"      → অ্যালার্ম + নোটিফিকেশন, থামো
           ৫ মিনিট শেষ      → হাল ছাড়ো, জানাও

সিট!     ছোট একটা "পাওয়া গেছে" নোট সেভ, নোটিফিকেশন,
         ওই ট্রেন আর ক্লাসের জন্য সাইটের নিজের রেজাল্ট পেজ খোলা

রিলোড    content.js নোট দেখে → অ্যালার্ম চালু, ট্রেনে স্ক্রল, BOOK NOW জ্বালানো
আপনি     BOOK NOW চাপেন → সাইট সিট-ম্যাপ আনে (আর নিজের বট-চেক চালায় — এক্সটেনশন ছোঁয় না)
         content.js পেজের পরিবর্তন দেখে (MutationObserver) → সেরা খালি সিট দাগায়
         আর প্রতিটি সিট কোন দিকে মুখ করা তা অনুমান করে (⬆ / ⬇ / ⬆→⬇)
         ← এই ধাপে এক্সটেনশন কোনো নেটওয়ার্ক রিকোয়েস্ট করে না
আপনি     সিট চাপেন → CONTINUE PURCHASE → OTP → পেমেন্ট

লগইন কোথা থেকে আসে

আপনি সাইটে স্বাভাবিকভাবে লগইন করেন। সাইট আপনার সেশন পেজের localStorage-এ রাখে (একটি টোকেন আর একটি ডিভাইস আইডি ও কী)। পাহারাদার সেগুলো পড়ে, আর সাইট নিজে যে হেডার ব্যবহার করে (Authorization, X-Device-Id, X-Device-Key) সেভাবেই খোঁজার সাথে পাঠায়। এগুলো শুধু রেলের নিজের টিকিট সার্ভারে যায় (eticket.railway.gov.bd যেটা ব্যবহার করে) — এক্সটেনশন জমিয়ে রাখে না, অন্য কোথাও পাঠায় না। আপনার পাসওয়ার্ড কখনো দেখে না।

অ্যালার্ম কেন লুকানো পেজ থেকে বাজে

আপনি ক্লিক না করা পর্যন্ত ব্রাউজার কোনো পেজকে আওয়াজ করতে দেয় না ("autoplay policy")। টিকিট ছাড়ার সময়ের ট্যাবটা নিজে থেকে খোলা, তাই সেটা আওয়াজ করতে পারে না। এক্সটেনশন একটি offscreen পেজ থেকে আওয়াজ বাজাতে পারে, তাই সাইরেন সেখানে বাজে। টুলস → অ্যালার্ম শুনে দেখুন-ও একই পথে বাজে, তাই পরীক্ষাটা সত্যিকারের।

"এটি কি মানুষের মতো আচরণ করে?" — সত্যি বললে, না

এখানে পরিষ্কার থাকা দরকার, কারণ "মানুষ সাজা" বলতে সাধারণত বট-ধরা ব্যবস্থাকে ধোঁকা দেওয়ার কৌশল বোঝায়। এই এক্সটেনশন ইচ্ছে করেই সেসব করে না।

যা করে

যা করে না

এলোমেলো বিরতিটা ছদ্মবেশ নয়। খুঁটিয়ে দেখলে সার্ভার ঠিকই বুঝতে পারে রিকোয়েস্টগুলো স্ক্রিপ্ট থেকে আসছে: ঠিক দুপুর ২:০০:০০-এ শুরু হওয়া সমান-দূরত্বের কল, পেজে কোনো ক্লিক ছাড়া। সুরক্ষাটা আসে পরিমাণ আর সময় থেকে — সার্ভার যতটা মেনে নেয় তার ভেতরে থাকা — লুকিয়ে থাকা থেকে নয়।

ব্লক এড়াতে এটি কী করে

ব্যবস্থাকেনকোথায়
ছাড়ার আগে শুরুই করে নাএই রানের সময়ের মধ্যে তারিখ না ছাড়লে খোঁজা অর্থহীন, শুধু রিকোয়েস্ট বাড়ে। বার্তা দিয়ে থেমে যায়।content.js · runEngine()
সার্ভারের ঘড়িতে ছাড়ার ০.৫ সেকেন্ড আগে শুরু"যদি লাগে" ভেবে আগে খোঁজে না। ঘড়ির পার্থক্য একটি HTTP Date হেডার থেকে।serverOffsetMs(), startLeadMs
সেকেন্ডে ≈ ১বার খোঁজা৭০০ মিলিসেকেন্ড + ০–২৫০ এলোমেলো, সাথে রিকোয়েস্টের সময়। বদলানো যায় (কমপক্ষে ৩০০) — কমাবেন না।pollIntervalMs
429 পেলে পিছিয়ে যায়সার্ভার "খুব ঘন ঘন" বললে ২ → ৪ → ৮ → ১৫ সেকেন্ড অপেক্ষা।খোঁজার লুপ
প্রথম সিট পেলেই থামেআপনার ক্লাসে অনলাইন সিট দেখা মাত্র খোঁজা বন্ধ।খোঁজার লুপ
কঠিন সময়সীমা৫ মিনিট পর হাল ছাড়ে (সর্বোচ্চ ১৫)। সবচেয়ে খারাপ ক্ষেত্রে ≈ ৩০০ বার খোঁজা।maxWaitMinutes
401 পেলে থামেলগআউট হওয়া সেশনে আবার চেষ্টা করে না।খোঁজার লুপ
সিট দাগানো অফলাইনআগে থেকে লোড হওয়া পেজটাই পড়ে। বগি বদলালেও কোনো রিকোয়েস্ট নেই। সিট সোজা না উল্টো, তা রুট আর ম্যাপ থেকেই বের করে, কিছু খোঁজে না।suggestSeats()
বট-চেকে কখনো হাত দেয় নাসিট-ম্যাপের রিকোয়েস্টে Turnstile টোকেন লাগে। এক্সটেনশন সেটা কখনো কল করে না — সিট-ম্যাপ খোলে আপনার ক্লিকে।—
সব জায়গায় থামানোর বোতামপ্যানেল আর পেজের স্ট্যাটাস বক্স — দুটোই সাথে সাথে থামায়।stopRun

আপনার দিক থেকে: যে তারিখ ছাড়েনি সেটায় বারবার টেস্ট নয়, এক ট্রিপে দুই কম্পিউটারে ARM নয়, আর রানের সময় অনেকগুলো টিকিট সাইটের ট্যাব খোলা নয়।

সীমাবদ্ধতা

অসুবিধা ও ঝুঁকি

কোড নিয়ে কাজ

  1. রিপো ক্লোন করুন। এক্সটেনশন আছে shohoz-autobook/ ফোল্ডারে।
  2. brave://extensions → Developer mode → Load unpacked → ওই ফোল্ডার।
  3. কোড বদলানোর পর এক্সটেনশন কার্ডে ↻ চাপুন আর টিকিট সাইটের ট্যাব রিলোড করুন।
  4. এখনই কেনা যায় এমন তারিখে ▶ এখনই টেস্ট করুন দিয়ে পরীক্ষা করুন। লগ দেখতে স্ট্যাটাস বক্সের বিস্তারিত ▾ খুলুন।

দরকারি মানগুলো

সেটিংডিফল্টকোথায়
ছাড়ার কত আগে ট্যাব খোলে৭৫ সেকেন্ডbackground.js-এ PRELAUNCH_LEAD_MS
ছাড়ার কত আগে খোঁজা শুরু৫০০ মিলিসেকেন্ডbackground.js-এর ডিফল্টে startLeadMs
দুই খোঁজার মাঝে বিরতি৭০০ + ০–২৫০ মিলিসেকেন্ডpollIntervalMs (প্যানেল → অ্যাডভান্সড)
কতক্ষণ পর হাল ছাড়ে৫ মিনিটmaxWaitMinutes (প্যানেল → অ্যাডভান্সড)
"সিট খুলেছে" অবস্থা কতক্ষণ থাকে১৫ মিনিটcontent.js-এ ASSIST_TTL_MS
বিক্রির সময়সীমা১০ দিনSALE_WINDOW_DAYS

অবদান রাখতে চাইলে

Issue আর pull request স্বাগত — বিশেষ করে সাইটের ডিজাইন বদলালে ঠিক করা, ছাড়ার সময় আপডেট আর অনুবাদ ঠিক করা। বট-চেক এড়ানো, লগইন/OTP/পেমেন্ট অটোমেট করা বা রিকোয়েস্টের গতি বাড়ানোর মতো পরিবর্তন নেওয়া হবে না।