Discord bot ზუსტად იმდენ ხანს არის ონლაინ, რამდენ ხანსაც მისი პროცესი მუშაობს. არ არსებობს რიგი, რომელიც მას გააღვიძებს, და არც მოთხოვნა, რომელიც მოთხოვნისას გაუშვებს: თუ პროცესი gateway-სთან არ არის დაკავშირებული, bot ოფლაინად ჩანს და ყველა slash command ჩავარდება შეტყობინებით "The application did not respond". ამიტომ bot-ის 24/7 ჰოსტინგი ერთ უშნო საქმეს ნიშნავს - პატარა Node პროცესი უნდა იმუშაოს იმ მანქანაზე, რომელიც შენი ლეპტოპი არ არის, მისი გაჩერებისას უნდა გაეშვას თავიდან, ცვლილებისას კი ხელახლა deploy-დეს.
ეს არის discord.js bot-ის მთელი გზა: აპლიკაცია და მისი token, intents, რომლებსაც აცხადებ, პროექტის სტრუქტურა, რომელიც სერვერზე სუფთად ეშვება, slash command-ების რეგისტრაცია, deploy GitHub-იდან და რამდენიმე ჩავარდნა, რომელიც bot-ებს ღამის სამ საათზე ათიშავს. ზომა ცალკე საკითხია და პასუხი გაცემულია პოსტში რამდენი RAM და CPU სჭირდება Discord bot-ს; მოკლედ, რამდენიმე ათეულ სერვერში მყოფი command bot-ისთვის ყველაზე პატარა გეგმაც ჯდება.
რას მოითხოვს დღე-ღამის განმავლობაში მუშაობა#
შენი bot ხსნის ერთ გამავალ WebSocket-ს Discord gateway-სთან და მას ღიად ინახავს. Discord აგზავნის hello payload-ს, რომელშიც არის heartbeat_interval (ჩვეულებრივ ორმოც წამზე ცოტა მეტი), ბიბლიოთეკა კი ამ ინტერვალით აგზავნის heartbeat-ს, სანამ კავშირი ცოცხალია. მოვლენები ამ socket-ზე მოდის; ყველაფერი, რასაც bot უკან აკეთებს - პასუხი, რედაქტირება, command-ების რეგისტრაცია - REST API-ით მიდის, ჩვეულებრივი HTTPS მოთხოვნებით.
აქედან ორი დასკვნა გამომდინარეობს და ორივე განსაზღვრავს, როგორ უნდა გაუშვა bot.
- არაფერს არ სჭირდება bot-თან გარედან მოსვლა. არც შემომავალი პორტი, არც დომენი, არც სერტიფიკატი, არც firewall-ის წესი. bot NAT-ის უკანაც უპრობლემოდ მუშაობს. თუ მოგვიანებით web dashboard-ს დაამატებ, ის მეორე, განსხვავებული სერვისია თავისი მოთხოვნებით.
- პროცესი მუდმივად უნდა იყოს გაშვებული. პლატფორმები, რომლებიც აპლიკაციას HTTP ტრაფიკის გარეშე გარკვეული დროის შემდეგ აძინებს, არ ვარგა, რადგან bot HTTP ტრაფიკს საერთოდ არ იღებს. ნებისმიერი სქემა, სადაც პროცესი თითო მოთხოვნაზე ჩერდება და ეშვება, ამ დატვირთვისთვის არასწორი ფორმაა.
| რა სჭირდება bot-ს | რა არ სჭირდება |
|---|---|
| პროცესი, რომელიც მუშაობს | შემომავალი პორტი |
| გამავალი HTTPS და WebSocket | დომენი ან სერტიფიკატი |
| restart, როცა პროცესი წყდება | load balancer |
| ადგილი state-ის შესანახად | ერთზე მეტი პროცესი 2 500 guild-მდე |
კიდევ ერთი, რაც deploy-მდე უნდა იცოდე: ხელახლა დაკავშირება უფასო არ არის. როცა socket წყდება, ბიბლიოთეკა ჯერ resume-ს ცდილობს: აგზავნის session ID-ს და ბოლო დანახულ თანმიმდევრობის ნომერს, Discord კი გამოტოვებულ მოვლენებს ხელახლა აგზავნის. თუ სესიის გაგრძელება ვერ ხერხდება, bot-მა ხელახლა უნდა გაიაროს identify, ხოლო identify-ებს ლიმიტი აქვს - bot-ების უმრავლესობას დღეში 1 000 აქვს. საკუთარ ლიმიტს ნახავ ავტორიზებული GET /gateway/bot-ით, რომელიც აბრუნებს session_start_limit ობიექტს ველებით total, remaining და reset_after. crash loop-ში მყოფი bot ამ ლიმიტს ხარჯავს, ამიტომ restart loop რეალური პრობლემაა და არა უბრალოდ ხმაური log-ში.
აპლიკაცია, token და invite#
ყველაფერი Discord Developer Portal-ში იწყება. შექმენი აპლიკაცია, გახსენი მისი Bot tab და გადააყენე token. ის ერთხელ ჩანს. თუ დაკარგე, ისევ გადააყენე - ძველი მაშინვე გაუქმდება და bot ოფლაინ იქნება, სანამ ახალ მნიშვნელობას deploy-ს არ გაუკეთებ.
bot token შედგება სამი base64-ის მსგავსი ნაწილისგან, წერტილებით გამოყოფილი, და პირველი ნაწილი შენი აპლიკაციის დაშიფრული ID-ია, ამიტომ გაჟონილი token ანონიმური არ არის: ვინც ხედავს, იცის, რომელ bot-ს ეკუთვნის. Discord GitHub-ის secret scanning-ში მონაწილეობს, ამიტომ საჯარო repository-ში ატვირთული token ჩვეულებრივ რამდენიმე წუთში უქმდება. ეს კარგი შედეგია. ცუდი ისაა, როცა token კერძო repository-შია, რომელიც მოგვიანებით საჯარო ხდება. მოექეცი მას, როგორც პაროლს, რომელიც bot-ზე სრულ კონტროლს იძლევა, და შეინახე გარემოს ცვლადში - სად შევინახოთ საიდუმლოები აპლიკაციის სერვერზე ზოგად შემთხვევას განიხილავს.
ამ გვერდზე ორი გადამრთველი ხშირად აბნევს ხალხს:
- Public bot განსაზღვრავს, შეუძლია თუ არა ნებისმიერს შენი bot-ის მოწვევა. კერძო bot-ისთვის გამორთე და სერვერებზე მხოლოდ შენ დაამატებ.
- Requires OAuth2 code grant გამორთული უნდა იყოს. ის ისეთი flow-სთვისაა, რომელსაც თითქმის არავინ იყენებს, ჩართულით კი ჩვეულებრივი invite ბმული გაუგებარი შეცდომით ვარდება.
Invite ააგე OAuth2, URL Generator-ში. მონიშნე bot და applications.commands როგორც scope-ები - bot, რომელიც applications.commands-ის გარეშეა მოწვეული, დაუკავშირდება, ონლაინ გამოჩნდება და slash command-ები არ ექნება; ეს "ჩემი command-ები არ ჩანს" პრობლემის ერთ-ერთი ყველაზე გავრცელებული მიზეზია. შემდეგ აირჩიე უფლებები, რომლებიც bot-ს ნამდვილად სჭირდება. უფლებების მოგვიანებით დამატება მხოლოდ ახალი ბმულით ხელახალი მოწვევით ან სერვერზე bot-ის როლის რედაქტირებით შეიძლება, ამიტომ ღირს ერთხელ დაფიქრდე და არა ყველა სერვერის მფლობელს ორჯერ სთხოვო.
Intents და რაზე იწერები სინამდვილეში#
Intents კავშირისას გამოცხადდება და ისინი განსაზღვრავს, საერთოდ რომელ მოვლენებს გამოგიგზავნის Discord. მათი არასწორად დაყენება შეცდომას კი არ იძლევა, არამედ სიჩუმეს, ამიტომ ღირს ყურადღებით მოქცევა.
import { Client, GatewayIntentBits, Partials } from "discord.js";const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, ], partials: [Partials.Message, Partials.Channel, Partials.Reaction],});Guilds პრაქტიკულად სავალდებულოა: მის გარეშე ბიბლიოთეკას არ აქვს guild-ის, არხის და როლის ქეში და API-ს უმეტესი ნაწილი წყვეტს მუშაობას. სამი intent პრივილეგირებულია და პორტალის Bot tab-ზე ცალკე უნდა ჩაირთოს: GUILD_MEMBERS, GUILD_PRESENCES და MESSAGE_CONTENT. როცა bot 100-ზე მეტ სერვერშია, მათ შესანარჩუნებლად ვერიფიკაცია უნდა გაიაროს, რაც ლოდინის პერიოდიანი პროცესია, ამიტომ წინასწარ გადაწყვიტე, გჭირდება თუ არა. მხოლოდ slash command-ებზე აგებულ bot-ს MESSAGE_CONTENT საერთოდ არ სჭირდება, რადგან command-ის payload interaction-თან ერთად მოდის.
partials მასივი მეორე ნახევარია. თუ მოვლენა ისეთ რამეს ეხება, რაც ბიბლიოთეკას ქეშში არ აქვს - მაგალითად, რეაქცია შეტყობინებაზე, რომელიც bot-ის გაშვებამდე გამოქვეყნდა - discord.js მოვლენას საერთოდ არ გამოსცემს, თუ ნაწილობრივ სტრუქტურებზე თანხმობა არ გაქვს მიცემული. partials-ით ჩართულზე იღებ მონახაზს და სრული ობიექტის საჭიროებისას მასზე .fetch()-ს იძახებ.
პროექტი, რომელიც თავისით ეშვება#
სერვერზე გაშვების ბრძანებას არავინ აკრეფს. ის უნდა მუშაობდეს ცივი container-იდან, git-იდან ახლახან გადმოწერილ დირექტორიაში, ინტერაქტიული shell-ის გარეშე.
{ "name": "my-bot", "type": "module", "engines": { "node": ">=20" }, "scripts": { "start": "node src/index.js", "register": "node scripts/register-commands.js" }, "dependencies": { "discord.js": "^14.16.3" }}ჰოსტზე გაშვების ბრძანებამ lockfile-იდან უნდა დააინსტალიროს და შემდეგ გაუშვას:
npm ci --omit=dev && node src/index.jsnpm ci შლის node_modules-ს და აყენებს ზუსტად იმას, რასაც lockfile ამბობს, და ხმამაღლა ვარდება, თუ lockfile და manifest ერთმანეთს არ ემთხვევა. npm install ჩუმად რაღაც ახალს ირჩევს, და ასე იღებს შენს მანქანაზე მომუშავე bot სერვერზე გატეხილ minor ვერსიას. დააკომიტე package-lock.json. განსხვავება დეტალურად აღწერილია პოსტში npm ci vs npm install.
ღირს ორი ვერსიული ხაფანგის დასახელება. პირველი: --omit=dev შლის devDependencies-ს, ამიტომ TypeScript bot ამ ფლაგით სერვერზე ვერ დაკომპილირდება: ან CI-ში ააგე და dist გაგზავნე, ან --omit=dev მოაშორე და ინსტალაციის ზომას შეეგუე. მეორე: discord.js-მა v14-ის სიცოცხლის განმავლობაში Node-ის მინიმალური ვერსია აწია, ხოლო engines ადამიანებისთვის შენიშვნაა და container მას არ ამოწმებს. ამიტომ ვერსია გაშვებისას დაბეჭდე და არ დაუშვა:
import { Events } from "discord.js";client.once(Events.ClientReady, () => { console.log(`node ${process.version}, logged in as ${client.user.tag}`); console.log(`guilds: ${client.guilds.cache.size}`);});ეს ორი ხაზი სამ კითხვას წინასწარ პასუხობს: რომელი Node მუშაობს, token იმუშავა თუ არა და რამდენ სერვერს ხედავს bot. გამოიყენე Events მუდმივა და არა სტრიქონის ლიტერალი, რადგან მოვლენების სახელები გამოშვებებს შორის შეიცვალა, მუდმივა კი შენ მიერ დაყენებულ ვერსიას მიჰყვება.
კიდევ ერთი დეტალი გარემოზე: სერვერის container-ები UTC-ში მუშაობს, თუ სხვაგვარად არ უთხარი. თუ შენი bot ყოველდღიურ შეტყობინებას 09:00-ზე აქვეყნებს, ის 09:00 UTC-ზე გამოაქვეყნებს. დააყენე TZ გარემოს ცვლადი ან გამოთვლა კოდში აშკარად გააკეთე. ჩუმი დროის სარტყლის გადახრა ამ კატეგორიის ყველაზე გამაღიზიანებელი bug-ია, რადგან ის მხოლოდ ფიქსირებული საათების რაოდენობით არის არასწორი.
Slash command-ების რეგისტრაცია რამის გაფუჭების გარეშე#
Command-ები რეგისტრირდება REST API-ით და არა gateway-ით, და Discord-ის მხარეს ინახება. ეს ნიშნავს, რომ რეგისტრაცია deploy-ის ნაბიჯია და არა გაშვების.
import { REST, Routes } from "discord.js";const commands = [ { name: "ping", description: "Check that the bot is alive" },];const rest = new REST().setToken(process.env.DISCORD_TOKEN);await rest.put( Routes.applicationGuildCommands(process.env.APP_ID, process.env.GUILD_ID), { body: commands },);applicationGuildCommands ერთ სერვერში არეგისტრირებს და მაშინვე მოქმედებს, რაც დეველოპმენტისას გჭირდება. applicationCommands გლობალურად არეგისტრირებს; Discord-ის დოკუმენტაციით გლობალური command-ების გავრცელებას ერთ საათამდე სჭირდება, ამიტომ command, რომელიც გლობალური რეგისტრაციისთანავე არ ჩანს, ჩვეულებრივ უბრალოდ ჯერ ადრეა. PUT მთელ ნაკრებს ანაცვლებს, ამიტომ ყველაფერი, რაც მასივში არ არის, წაიშლება - ასე შლი ძველ command-ს და ასევე ასე წაუშლიათ შემთხვევით ადამიანებს საკუთარი command-ების სია არასრული მასივის რეგისტრაციით.
რეგისტრაცია ყოველ გაშვებაზე არ გაუშვა. Discord-ს დღეში შექმნილი command-ების რაოდენობაზე ლიმიტი აქვს, ხოლო bot-მა, რომელიც restart loop-ში მოხვედრისას ყოველ გაშვებაზე არეგისტრირებს, თავი შეიძლება დღის ბოლომდე დაბლოკოს. გაუშვი ის ცალკე ბრძანებად, როცა command-ების აღწერა იცვლება, რაც bot-ების უმრავლესობისთვის იშვიათად ხდება.
თუ რეგისტრაცია ვარდება შეტყობინებით Invalid Form Body და შეცდომის კოდით 50035, წაიკითხე ველის გზა შეტყობინებაში. command-ის სახელები პატარა ასოებით უნდა იყოს, 1-32 სიმბოლო, ჰარის გარეშე; აღწერა 1-100 სიმბოლოა და chat input command-ებისთვის სავალდებულოა. შეცდომა ზუსტია, როგორც კი იცი, რომ ის კონკრეტულ პარამეტრზე მიუთითებს.
Deploy GitHub-იდან#
zip ფაილის ატვირთვა ისეთი სერვერის გზაა, რომლის შიგთავსსაც ვერავინ ამოიცნობს. ამის ნაცვლად repository მიაერთე.
RE:NODE-ზე Git ინტეგრაცია მხოლოდ GitHub-ისაა, GitHub App-ის მეშვეობით, რომელიც მოკლევადიან token-ებს გასცემს და არ გთხოვს არასდროს გასაუქმებელი personal access token-ის ჩასმას, ამიტომ კერძო repository-ები მუშაობს და სერვერზე სამუდამოდ credential არ რჩება. ორი დამოუკიდებელი გადამრთველია: branch-ის pull ყოველ container-ის გაშვებაზე და deploy on push, რომელიც სერვერს restart-ს უკეთებს, როცა GitHub ამ branch-ზე push-ს აცხადებს - და მხოლოდ იმ შემთხვევაში, თუ ის უკვე გაშვებული იყო, ამიტომ განზრახ გაჩერებული სერვერი გაჩერებული რჩება. ყოველი deploy ერთ ჩანაწერად ინახება, იხსნება push-ის მოსვლისას და იხურება, როცა container ხელახლა გაშვებული ჩანს, რითიც გარჩევ deploy-ს, რომელიც გავიდა, იმისგან, რომელიც ჩავარდა. ინსტრუქცია არის პოსტში Node.js აპლიკაციის deploy GitHub-იდან.
Deploy მოკლე დაცარიელებას ჯდება: პროცესი ჩერდება, pull და ინსტალაცია სრულდება, bot ხელახლა უკავშირდება, ჩვეულებრივ ხუთიდან ოცი წამის განმავლობაში. ამ ფანჯარაში bot-ისთვის გაგზავნილი ნებისმიერი interaction ვარდება. ერთი პროცესით ამის გვერდის ავლა შეუძლებელია, ამიტომ deploy გააკეთე, როცა მომხმარებლები სძინავთ, და ინსტალაცია სწრაფად შეინარჩუნე - zero-downtime deploy სერვერზე, რომელსაც ყველაფერი ერთი აქვს გულახდილია, რომელი ტექნიკა gateway bot-ს ეხება.
თუ bot მნიშვნელოვანია, მიეცი staging ტყუპისცალი: მეორე აპლიკაცია Developer Portal-ში საკუთარი token-ით, მოწვეული მხოლოდ შენს სატესტო სერვერზე. Staging და production ერთ ანგარიშზე შეიცავს ამ ნიმუშს.
საიდუმლოები, state და ფაილები, რომლებსაც bot წერს#
გარემოს ცვლადები Startup tab-ზე მიდის და არა repository-ში. DISCORD_TOKEN, აპლიკაციის ID, ნებისმიერი API გასაღები, მონაცემთა ბაზის URL. დაამატე .env .gitignore-ში პირველივე დღეს და მნიშვნელობები ისე წაიკითხე, რომ არარსებობისას მკაცრად ჩავარდეს:
const token = process.env.DISCORD_TOKEN;if (!token) throw new Error("DISCORD_TOKEN is not set");გაშვებისას ნათელი შეტყობინებით ჩავარდნა ბევრად უკეთესია, ვიდრე undefined-ით დაკავშირება და კონსოლში An invalid token was provided-ის კითხვა.
State მეორე ნახევარია. ყველაფერი, რასაც bot საკუთარ repository დირექტორიაში წერს, შემდეგ pull-ს ხელს უშლის, ამიტომ გაშვების მონაცემები ისეთ ადგილას შეინახე, რომელსაც deploy არ ეხება: დირექტორია თვალთვალადი ხის გარეთ, ან მონაცემთა ბაზა. SQLite ფაილი გასაკვირად ბევრი bot-ის სწორი პასუხია - ერთი ფაილი, სერვერის გარეშე, და ის bot-ის ჩაწერის მოცულობას შეუმჩნევლად უმკლავდება. ქსელურ მონაცემთა ბაზაზე გადადი, როცა ერთზე მეტი პროცესი წერს ან როცა მონაცემები მეხსიერებაში კომფორტულად აღარ ეტევა. აპლიკაციის გეგმებში შედის ორი მონაცემთა ბაზის სლოტი, რომლებიც პანელში იქმნება გენერირებული host-ით, მომხმარებლითა და პაროლით, ხოლო როცა საცავი bot-ს აღემატება, არსებობს ცალკე ხაზები მონაცემთა ბაზის ჰოსტინგში; connection pool-ები და ლიმიტები აღწერს შეცდომას, რომელსაც bot-ების უმეტესობა პირველად უშვებს - თითო command-ზე ერთი კავშირის გახსნას.
რასაც არ უნდა იყენებდე, backup გააკეთე განრიგით და არა მაშინ, როცა გაგახსენდება. Backup სლოტები ყველა აპლიკაციის გეგმას მოჰყვება და Schedules tab მათ cron გამოსახულებით უშვებს. backup, რომელიც არავის აღუდგენია, ჰიპოთეზაა: backup-ები, რომლებიც ნამდვილად აღდგება ამ აზრს სათანადოდ ასაბუთებს.
ონლაინ დარჩენა: crash-ები, loop-ები და მეხსიერების ლიმიტი#
სამი რამ აჩერებს მომუშავე bot-ს და სამივე თავიდან აცილებადია.
დაუმუშავებელი rejection პროცესს ასრულებს. მიმდინარე Node-ში დაუმუშავებელი promise rejection პროცესს ნაგულისხმევად წყვეტს. საკმარისია command handler-ში ერთი ჩავარდნილი fetch catch-ის გარეშე. დააყენე handler-ები და log ხაზი გააკეთე მანამდე, სანამ რამე დასრულდება:
process.on("unhandledRejection", (error) => { console.error("unhandled rejection:", error);});process.on("SIGTERM", async () => { await client.destroy(); process.exit(0);});client-ის დახურვა SIGTERM-ზე უფრო მნიშვნელოვანია, ვიდრე ჩანს. bot, რომელიც socket-ის დახურვის გარეშე შეწყდა, ერთ წუთამდე ონლაინ ჩანს, ამიტომ ათწამიანი restart მომხმარებლებს ისე ეჩვენებათ, თითქოს bot მათ ერთი წუთი უგულებელყოფდა. Graceful shutdown და health check-ები ზოგად ნიმუშს შეიცავს.
მეხსიერების ლიმიტი მშვიდი მოვლენა არ არის. container-ის ლიმიტზე kernel პროცესს აჩერებს და ის სუფთად ეშვება, swap-ში დარჩენის ნაცვლად. bot-ისთვის ეს სწორი ნაგულისხმევია, მაგრამ ნიშნავს, რომ შეუზღუდავი ქეში ან მზარდი Map ნელი დაქვეითების ნაცვლად საიდუმლოებით მოცული restart-ის სახით ჩანს ყოველ რამდენიმე საათში. ნებისმიერი ცვლილების შემდეგ ერთი დღე უყურე კონსოლში მეხსიერების გრაფიკს; რატომ კვდება შენი Node აპლიკაცია 2 GB-ზე 4 GB-იან გეგმაზე ხსნის მეორე ჭერს, V8 heap-ს, რომელსაც Node პროცესი ჩვეულებრივ პირველად ეჯახება.
restart loop შეიმჩნევა. RE:NODE-ზე watcher ყოველ ორ წუთში ამოწმებს სერვერს, რომელიც ოფლაინ გახდა ან რომლის uptime უკან წავიდა, და შენ მიერ მოთხოვნილ restart-ებს უგულებელყოფს. ერთ საათში სამი მოულოდნელი restart სერვერის გვერდზე გაფრთხილებას აჩენს და ticket-ს ხსნის; ექვსი კი შეჩერებამდე მიდის. ეს თვითნებური არ არის: bot, რომელიც ყოველ ოც წამში restart-დება, gateway-ს ბომბავს და ზემოთ აღწერილ identify ლიმიტს ხარჯავს. რატომ ხდება შენი სერვერის განუწყვეტელი restart loop-ის დიაგნოსტიკას აღწერს.
მონიტორინგისთვის გახსოვდეს, რომ bot-ს არ აქვს endpoint, რომელსაც გამოკითხავ. ან კონსოლი იკითხე, ან პატარა HTTP სერვერი მიაბი გეგმასთან მოსულ პორტზე და uptime monitor proxy სლოტით მიუთითე. მონიტორინგი, რომელიც რამეს გეუბნება ამ სიის მოკლედ შენახვაზეა.
პრობლემების მოგვარება#
bot ონლაინ არის, მაგრამ command-ები არ აქვს. ან invite-ს applications.commands scope აკლდა, ან command-ები გლობალურად დარეგისტრირდა და ჯერ არ გავრცელებულა. დარეგისტრირე შენს სატესტო guild-ში, რომ წამებში შეამოწმო.
"The application did not respond". შენმა handler-მა სამ წამში პასუხი ვერ გასცა. ან შეცდომა გამოაგდო, ან ნამდვილ საქმეს აკეთებს. ჯერ გამოიძახე interaction.deferReply(), რომელიც ფანჯარას თხუთმეტ წუთამდე ზრდის, შემდეგ კი, როცა პასუხი გაქვს, editReply().
დახურვის კოდი 4004 loop-ში. ცუდი token. ჩვეულებრივ გადაყენებული token, რომელსაც deploy არ გაუკეთდა, ცვლადის სახელის შეცდომა ან bot token-ის ნაცვლად client secret-ის ჩასმა.
დახურვის კოდი 4014 loop-ში. პრივილეგირებული intent, რომელიც Developer Portal-ში ჩართული არ არის.
`Missing Permissions` (50013) ან `Missing Access` (50001). ყველაზე ხშირად როლების იერარქია. bot ვერ მოდერირებს წევრს, რომლის უმაღლესი როლი bot-ის საკუთარზე მაღლაა, უფლებების მიუხედავად, და ვერ დაწერს არხში, სადაც არხის override მას უარყოფს.
HTTP 429 და შემდეგ არაფერი. rate limit-ზე ხარ; პასუხს retry_after აქვს და ბიბლიოთეკა მას ელოდება. უარყოფილი მოთხოვნების მდგრადი წყალდიდობა უარესია, ვიდრე ნელი, რადგან Discord-ის edge ბლოკავს მისამართებს, რომლებიც მოკლე ფანჯარაში ბევრ არასწორ მოთხოვნას აგზავნის. loop გაასწორე და ნუ ცდი უფრო ძლიერად - rate limit-ები და abuse ზოგად სურათს გვაძლევს.
FAQ#
შემიძლია Discord bot უფასოდ გავუშვა?
შეგიძლია გაუშვა სახლში მყოფ სათადარიგო კომპიუტერზე, და ის ოფლაინ იქნება, როცა ეს მანქანა ძინავს, განახლდება ან ინტერნეტი არასტაბილურია. უფასო აპლიკაციის გეგმები ჩვეულებრივ აჩერებს პროცესს, რომელიც HTTP ტრაფიკს არ იღებს, gateway bot-ი კი ზუსტად ასეთია. აქ უფასო გეგმა არ არსებობს; ყველაზე პატარა app გეგმა 1 GB-ია 0.5 vCPU-ით, თვეში $4-დან, რაც command bot-ისთვის საჭიროზე მეტია.
სჭირდება თუ არა Discord bot-ს ღია პორტი ან დომენი?
არა. Discord-თან კავშირი გამავალია, ამიტომ bot-ს არც შემომავალი პორტი სჭირდება და არც სერტიფიკატი. დომენი მხოლოდ მაშინ გჭირდება, თუ dashboard-ს ან OAuth callback-ს დაამატებ, და ამ შემთხვევაში app გეგმის proxy სლოტი შენს მაგივრად hostname-სა და სერტიფიკატს აგვარებს.
რატომ ჩანს ჩემი bot ოფლაინ, როცა პროცესი მაინც მუშაობს?
იმიტომ, რომ Discord-ისთვის gateway კავშირი ჩანს და არა პროცესი. დაბლოკილი event loop - გრძელი სინქრონული ციკლი, უზარმაზარი JSON parse, სინქრონული ფაილის წაკითხვა - heartbeat-ების გაგზავნას აჩერებს, Discord socket-ს ხურავს და bot ოფლაინ ჩანს, container კი სრულიად ჯანსაღ CPU-სა და მეხსიერებას აჩვენებს. ნელი სამუშაო მთავარი გზიდან გადაიტანე.
უნდა გავუკეთო თუ არა slash command-ებს ხელახალი რეგისტრაცია ყოველ deploy-ზე?
არა და არც უნდა. რეგისტრაციები Discord-ის მხარეს რჩება, სანამ არ შეცვლი. გაუშვი რეგისტრაციის სკრიპტი, როცა command-ების აღწერა იცვლება, და გაშვების ბრძანებაში ნუ ჩასვამ.
როგორ გადავიტანო bot ჩემი კომპიუტერიდან სერვერზე?
ატვირთე კოდი GitHub-ზე token-ის გარეშე, შექმენი app სერვერი, მიაერთე repository, Startup tab-ზე დააყენე გარემოს ცვლადები, დააყენე გაშვების ბრძანება და გაუშვი. შემდეგ შენს კომპიუტერზე მყოფი ასლი გააჩერე - ერთ token-ზე ორი პროცესი ერთსა და იმავე სესიას ეჯიბრება და ძალიან გაუგებარ ქცევას იძლევა.
რა ხდება, როცა bot მეხსიერების ლიმიტს მიაღწევს?
container ჩერდება და სუფთად ეშვება, swap-ის ნაცვლად. კარგავ ყველაფერს, რაც მხოლოდ მეხსიერებაში იყო, ამიტომ მნიშვნელოვანი შეინახე. თუ ეს განმეორებით ხდება, მეტი მეხსიერების ყიდვამდე შეზღუდე ბიბლიოთეკის ქეშები და საკუთარი კოლექციები; როდის გაზარდო გეგმა სწორედ ამ ორი შემთხვევის გარჩევას ეხება.




კომენტარები
სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.