Tady
Հրապարակային Discord-բոտ սերվերների համար՝ 2500+ սերվեր և 260 000+ օգտատեր գագաթնակետին։ Շարդերի սեփական մենեջեր PHP-ով, Redis ակտիվ վիճակի համար, ինտերֆեյս երկու լեզվով։

Տեխնոլոգիաներ
- PHP
- DiscordPHP
- MySQL
- Redis
- JavaScript
- discord.js
- Node.js
Խնդիրը
Discord-ի համայնքներում, որտեղ ես շփվում էի, պարբերաբար պակասում էին նույն գործառույթները՝ մասնակիցներին պատահականորեն թիմերի բաժանել, ստեղծել հաշվիչ ալիքներ, ռուսերենով խաղարկություններ անցկացնել անհրաժեշտ պայմաններով և սերվերն ավելի հարմար մոդերացնել։ Առկա բոտերը լուծում էին միայն առանձին խնդիրներ, իսկ ամբողջ անհրաժեշտ հավաքածուն նույնիսկ մի քանի լուծումից հավաքել չէր ստացվում։ Այդ պատճառով Tady-ն սկսվեց որպես մի քանի Discord-սերվերի համար նախատեսված մասնավոր բոտ։
Լուծումը
Երբ պարզ դարձավ, որ նույն սցենարներն անհրաժեշտ են նաև այլ համայնքների, բոտը դարձավ հրապարակային։ Բոտն արագ հավաքեց հարյուր սերվեր, իսկ այդ շեմից սկսած Discord-ը պահանջում է պարտադիր վավերացում։ Առանձին գործընթաց էր արտոնյալ intent-ների ստուգումը, առանց որոնց հրամանների մի մասը չի աշխատում։ Նախագծի աճին զուգընթաց ես ճարտարապետությունը հարմարեցրի մասշտաբին՝ շարդավորում, Redis ակտիվ վիճակի համար և բազմալեզու ինտերֆեյս։
Ճարտարապետություն
Հիմնական տեխնիկական որոշումները
- Շարդերի մենեջեր. Discord-ի հետ միացումը բաժանված է մի քանի Gateway-միացումների, և դրանցից յուրաքանչյուրն աշխատում է առանձին PHP-պրոցեսում։ DiscordPHP-ն ընդունում է շարդի համարը, բայց պրոցեսները չի կառավարում, ուստի նախագծում իրականացված է դրանց գործարկման, վերահսկման և վերագործարկման սեփական մենեջեր։
- Redis-ը՝ որպես ակտիվ վիճակի շերտ, բազան՝ որպես տվյալների հիմնական աղբյուր. վերագործարկման ժամանակ բոտը վիճակը վերականգնում է բազայից, իսկ նոր խաղարկությունները գրում է միանգամից երկու տեղ։
- Լեզուն վերցվում է հենց օգտատիրոջ Discord-ի կարգավորումներից, անգլերենը՝ պահեստային տարբերակ. ռուսալեզու լսարանով սերվերում ոչ ոք ստիպված չէ լեզուն ձեռքով փոխել։
- Սխալների մշակումը տարբերակում է խնդրի աղբյուրը՝ իրավունքը պակասում է օգտատիրոջը, թե բոտին, իսկ իրավունքի անվանումը ցուցադրվում է հրամանը կանչողի լեզվով։
- Արտոնյալ intent-ները կրճատվել են մինչև անհրաժեշտը. վավերացման ժամանակ հայցվել էին բոլոր երեքը, բայց Presence-ն այլևս պետք չէ, և ընթացիկ ստուգման մեջ մնում են միայն Members-ը և Message Content-ը։
Մասշտաբ և շարդավորում
Երբ բոտն աճեց մինչև 2500+ սերվեր, նախագիծն անցավ Discord-ի շարդավորման, որն այդ մասշտաբում պարտադիր է։
Discord-ում շարդը Gateway-ի առանձին միացում է։ Սերվերները (Discord API-ում՝ guild-ները) շարդերի միջև բաշխվում են իրենց ID-ից բխող բանաձևով, ընդ որում մեկ շարդը սպասարկում է առավելագույնը 2500 սերվեր։ DiscordPHP-ն ընդունում է շարդավորման պարամետրերը, բայց շարդ-պրոցեսների պատրաստի մենեջեր չի տրամադրում, ուստի Tady-ի համար իրականացվեց սեփականը. յուրաքանչյուր շարդ աշխատում էր առանձին PHP-պրոցեսում, իսկ գործարկումը, վերահսկումը և վերագործարկումն ավտոմատացված էին։ Պրոցեսների միջև վիճակը մնում էր ընդհանուր. Redis-ը պահում էր ակտիվ խաղարկությունները և ժամաչափերը, իսկ MySQL-ը ծառայում էր որպես տվյալների հիմնական աղբյուր և պահպանում էր մշտական վիճակը։ Շարդ-պրոցեսի վերագործարկման ժամանակ ակտիվ վիճակը չէր կորչում, այլ վերականգնվում էր MySQL-ից Redis-ում՝ խաղարկությունները, LFG-ն, հաշվիչ ալիքները և պահպանվող մյուս սցենարները։
Նախագծի զարգացման ընթացքում իրականացվել է առանձին տարբերակ Node.js-ով և discord.js-ով։ Հետագայում այդ ճյուղի զարգացումը դադարեցվել է, իսկ ընթացիկ production-ը մնացել է PHP-ի և DiscordPHP-ի վրա։
Բազմալեզվություն
Բոտն աջակցում է ռուսերեն և անգլերեն։ Պատասխանները, կոճակների մակագրություններն ու օգնության հաղորդագրություններն ավտոմատ հարմարվում են այն լեզվին, որն օգտատերն ընտրել է Discord-ի ինտերֆեյսում։ Եթե ընտրված լեզուն չի աջակցվում, լռելյայն օգտագործվում է անգլերենը։

Սխալների մշակում
Բոտը տարբերակում է մերժման պատճառները և յուրաքանչյուրին պատասխանում է յուրովի։ Եթե իրավունք է պակասում, այն ստուգում է՝ պակասում է օգտատիրոջը, թե հենց բոտին, և իրավունքն անվանում է հրամանը կանչողի լեզվով։ Առանձին են մշակվում իրավունքների հետ կապ չունեցող դեպքերը՝ մասնակցի դերն ավելի բարձր է, ադմինիստրատորին հնարավոր չէ լռեցնել։ Յուրաքանչյուր պատասխան նշում է պատճառը և, որտեղ հնարավոր է, հաջորդ քայլը, իսկ եթե պարզել չհաջողվեց, հաղորդագրությունից կարելի է անմիջապես անցնել աջակցության սերվեր։

Տևողության ձևաչափ
Տևողությունը տրվում է տեքստով՝ առանց ձեռքով վայրկյանների կամ րոպեների վերածելու։ Օրինակ՝ 1d 3h 12m 10s գրառումը ճիշտ մեկնաբանվում է որպես 1 օր, 3 ժամ, 12 րոպե և 10 վայրկյան։ Այս ձևաչափն աշխատում է բոլոր այն հրամաններում, որտեղ պետք է նշել ժամկետ։

Խաղարկություններ
/giveaway հրամանը գործարկում է խաղարկություն, որն ինքն է ավարտվում ժամաչափով։ Տևողությունը տրվում է նույն ձևաչափով, ինչ մյուս հրամաններում։ Գործարկումից հետո բոտը հետևում է մնացած ժամանակին, ավտոմատ ամփոփում է արդյունքները և մասնակիցներից պատահականորեն ընտրում մեկ կամ մի քանի հաղթող։ Խաղարկության հեղինակը կարող է դիտել իր ընթացիկ խաղարկությունները, ավարտել դրանք ժամկետից շուտ և անհրաժեշտության դեպքում վերընտրել հաղթողներին։

Օգնություն և հուշումներ
Յուրաքանչյուր հրաման ունի կարճ նկարագրություն, հրահանգ և օրինակներ. դրանք կարելի է տեսնել /help-ով (հրամանների ցանկ) կամ /help <հրամանի անվանում>-ով (մանրամասներ կոնկրետ հրամանի մասին)։ Այդ պատասխանը տեսանելի է միայն նրան, ով հարցրել է, և ալիքում ավելորդ հաղորդագրություններ չի թողնում։

Աջակցության սերվեր
Բոտն ունի աջակցության սերվեր, որտեղ օգտատերերն օգնություն են ստանում, գտնում հաճախակի տրվող հարցերի պատասխանները և հետևում նախագծի նորություններին։ Բոտը երբեք զանգվածային հաղորդագրություններ չի ուղարկում օգտատերերի անձնական հաղորդագրություններում կամ սերվերներում։

Օժանդակ և զվարճալի հրամաններ
Հիմնական սցենարներից բացի Tady-ն ունի փոքր հրամաններ համայնքի առօրյայի համար. /teams-ը մասնակիցներին պատահականորեն բաժանում է թիմերի, /translit-ը մականունների համար կիրիլիցան վերածում է լատինատառի, /info-ն և /avatar-ը ցույց են տալիս հաշվի տվյալները, իսկ /counter-ը ստեղծում է հաշվիչ ալիքներ։ Առանձին կանգնած է /lfg-ը՝ խաղընկերների հավաքը. բոտը հրապարակում է գրառում՝ տեղերով և ժամանակով, մասնակիցները միանում են կոճակով, իսկ երբ խումբը լրանում է, բոտն ինքն է դա հայտարարում։

Արդյունքներ
- Անցել է Discord-ի վավերացումը և արտոնյալ intent-ների ստուգումը, առանց որոնց հրամանները չեն աշխատում մեծ թվով սերվերներում։
- Մի քանի համայնքի համար նախատեսված մասնավոր բոտից վերաճել է հրապարակային նախագծի, որը մինչ օրս աշխատում և սպասարկվում է։
- Շարդավորումը և ընդհանուր վիճակը թույլ տվեցին մասշտաբավորել բոտը՝ առանց ամբողջ բեռը մեկ Gateway-միացման կամ պրոցեսի կապելու։
Մետրիկաներ
- Discord-սերվեր գագաթնակետին
- 2500+
- օգտատեր գագաթնակետին
- 260 000+
Փաստեր
- Discord-ի աջակցության հայտերի համակարգում սխալի պատճառով վավերացումը տևեց 4 ամիս, և այդ ամբողջ ընթացքում հարթակը թույլ չէր տալիս օգտատերերին բոտը հրավիրել իրենց սերվերներ։