יצירת דיסקורד בוט עם Discord4J + Boot Spring

1. סקירה כללית

Discord4J היא ספריית Java עם קוד פתוח שניתן להשתמש בה בעיקר לגישה מהירה ל- API של Discord Bot. זה משתלב בכבדות עם Project Reactor כדי לספק ממשק API תגובתי שאינו חוסם לחלוטין.

נשתמש ב- Discord4J במדריך זה כדי ליצור בוט Discord פשוט המסוגל להגיב לפקודה מוגדרת מראש. אנו בונים את הבוט על גבי Spring Boot כדי להדגים כמה קל יהיה להגדיל את הבוט שלנו על פני תכונות רבות אחרות המופעלות על ידי Spring Boot.

כשתסיים, הבוט הזה יוכל להאזין לפקודה בשם "! Todo" וידפיס רשימת מטלות שהוגדרה סטטית.

2. צור יישום Discord

כדי שהבוט שלנו יקבל עדכונים מ- Discord ויפרסם תגובות בערוצים, נצטרך ליצור יישום Discord בפורטל מפתחי Discord ולהגדיר אותו לבוט. זהו תהליך פשוט. מכיוון ש- Discord מאפשר ליצור מספר יישומים או בוטים תחת חשבון מפתח יחיד, אל תהסס לנסות זאת מספר פעמים עם הגדרות שונות.

להלן השלבים ליצירת יישום חדש:

  • היכנס לפורטל מפתחי Discord
  • בכרטיסייה יישומים, לחץ על "יישום חדש"
  • הזן שם לבוט שלנו ולחץ על "צור"
  • העלה אייקון של אפליקציה ותיאור ולחץ על "שמור שינויים"

כעת, לאחר שקיים יישום, עלינו פשוט להוסיף לו פונקציונליות של בוט. זה יפיק את אסימון הבוט ש- Discord4J דורש.

להלן השלבים להפיכת יישום לבוט:

  • בכרטיסיה יישומים, בחר באפליקציה שלנו (אם היא עדיין לא נבחרה).
  • בכרטיסיה Bot, לחץ על "הוסף Bot" ואשר שאנחנו רוצים לעשות את זה.

עכשיו שהיישום שלנו הפך לבוט אמיתי, העתק את האסימון כדי שנוכל להוסיף אותו למאפייני היישום שלנו. היזהר לא לשתף אסימון זה בפומבי מכיוון שמישהו אחר יוכל לבצע קוד זדוני תוך התחזות לבוט שלנו.

עכשיו אנחנו מוכנים לכתוב קצת קוד!

3. צור אפליקציית Boot Boot

לאחר בניית אפליקציית Spring Boot חדשה, עלינו להיות בטוחים לכלול את תלות הליבה של Discord4J:

 com.discord4j discord4j-core 3.1.1 

Discord4J עובד על ידי אתחול א GatewayDiscordClient עם אסימון הבוט שיצרנו קודם. אובייקט לקוח זה מאפשר לנו לרשום מאזינים לאירועים ולהגדיר דברים רבים, אך לכל הפחות עלינו להתקשר לפחות ל- התחברות() שיטה. זה יציג את הבוט שלנו כמקוון.

ראשית, בואו נוסיף את אסימון הבוט שלנו application.yml קוֹבֶץ:

אסימון: 'שלנו-אסימון-כאן'

לאחר מכן, בואו נזריק אותו לא @תְצוּרָה בכיתה שבה אנו יכולים לייצר את שלנו GatewayDiscordClient:

@Configuration בכיתה ציבורית BotConfiguration {@Value ("$ {token}") אסימון מחרוזת פרטי; @Bean GatewayDiscordClient ציבורי gatewayDiscordClient () {להחזיר DiscordClientBuilder.create (אסימון) .build () .login () .block (); }}

בשלב זה נראה את הבוט שלנו כמקוון, אך הוא עדיין לא עושה כלום. בואו נוסיף קצת פונקציונליות.

4. הוסף מאזינים לאירועים

התכונה הנפוצה ביותר של צ'אט-בוט היא הפקודה. זוהי הפשטה שנראית ב- CLI כאשר משתמש מקליד טקסט כלשהו כדי להפעיל פונקציות מסוימות. אנו יכולים להשיג זאת בבוט הדיסקורד שלנו על ידי האזנה למסרים חדשים שמשתמשים שולחים ומענה בתגובות נבונות במידת הצורך.

ישנם סוגים רבים של אירועים אליהם אנו יכולים להקשיב. עם זאת, רישום מאזין זהה לכולם, אז בואו ניצור ממשק לכל המאזינים לאירועים שלנו:

ייבא discord4j.core.event.domain.Event; ממשק ציבורי EventListener {Logger LOG = LoggerFactory.getLogger (EventListener.class); Class getEventType (); ביצוע מונו (אירוע T); ברירת מחדל מונו handleError (שגיאה הניתנת לזריקה) {LOG.error ("לא ניתן לעבד" + getEventType (). getSimpleName (), שגיאה); החזר Mono.empty (); }}

כעת אנו יכולים ליישם ממשק זה לכמה שיותר discord4j.core.event.domain.Event הרחבות כמו שאנחנו רוצים.

לפני שניישם את מאזין האירועים הראשון שלנו, בואו ונשתנה את הלקוח שלנו @אפונה תצורה כדי לצפות ברשימה של EventListener כדי שיוכל לרשום כל אחד שנמצא באביב ApplicationContext:

@Bean GatewayDiscordClient הציבורי gatewayDiscordClient (רשימה eventListeners) {לקוח GatewayDiscordClient = DiscordClientBuilder.create (token) .build () .login () .block (); עבור (EventListener מאזין: eventListeners) {client.on (listener.getEventType ()) .flatMap (listener :: execute) .onErrorResume (מאזין :: handleError). subscribe (); } להחזיר לקוח; }

כעת, כל שעלינו לעשות בכדי לרשום מאזינים לאירועים הוא ליישם את הממשק שלנו ולהביא לו הערות לספרינג @רְכִיבהערות סטריאוטיפ מבוססות. ההרשמה תתרחש כעת אוטומטית עבורנו!

יכולנו לבחור לרשום כל אירוע בנפרד ובמפורש. עם זאת, בדרך כלל עדיף לנקוט בגישה מודולארית יותר להרחבת קוד טובה יותר.

הגדרת המאזין לאירועים שלנו הושלמה כעת, אך הבוט עדיין לא עושה דבר, אז בואו נוסיף כמה אירועים להאזנה.

4.1. עיבוד פיקוד

כדי לקבל פקודה של משתמש, אנו יכולים להאזין לשני סוגי אירועים שונים: MessageCreateEvent להודעות חדשות ו- MessageUpdateEvent להודעות מעודכנות. אולי נרצה רק להאזין להודעות חדשות, אך כהזדמנות למידה, נניח שאנחנו רוצים לתמוך בשני סוגי האירועים עבור הבוט שלנו. זה יספק שכבה נוספת של חוסן שהמשתמשים שלנו עשויים להעריך.

שני אובייקטים לאירוע מכילים את כל המידע הרלוונטי לגבי כל אירוע. במיוחד אנו מעוניינים בתוכן ההודעה, מחבר ההודעה ובערוץ אליו פורסמה. למרבה המזל, כל נקודות הנתונים הללו חיות ב הוֹדָעָה אובייקט ששני סוגי האירועים הללו מספקים.

ברגע שיש לנו את הוֹדָעָה, אנו יכולים לבדוק את המחבר כדי לוודא שהוא אינו בוט, אנו יכולים לבדוק את תוכן ההודעה כדי לוודא שהוא תואם לפקודה שלנו, ונוכל להשתמש בערוץ ההודעה כדי לשלוח תגובה.

מכיוון שנוכל לפעול באופן מלא משני האירועים באמצעותם הוֹדָעָה אובייקטים, בואו נשים את כל ההיגיון במורד הזרם במיקום משותף, כך ששני המאזינים לאירועים יוכלו להשתמש בו:

ייבא discord4j.core.object.entity.Message; מחלקה מופשטת ציבורית MessageListener {ציבורי מונו ציבורי Command (Message eventMessage) {return Mono.just (eventMessage) .filter (message -> message.getAuthor (). map (user ->! user.isBot ()). orElse (false)) .filter (הודעה -> message.getContent (). equalsIgnoreCase ("! todo")) .flatMap (הודעה :: getChannel) .flatMap (ערוץ -> channel.createMessage ("דברים לעשות היום: \ n - כתוב בוט \ n - לאכול ארוחת צהריים \ n - לשחק משחק ")). ואז (); }}

הרבה קורה כאן, אבל זו הצורה הבסיסית ביותר של פקודה ותגובה. גישה זו משתמשת בתכנון פונקציונלי תגובתי, אך ניתן לכתוב זאת באופן ציוני מסורתי יותר באמצעות לַחסוֹם().

קנה מידה בין פקודות בוט מרובות, הפעלת שירותים שונים או מאגרי נתונים, או אפילו שימוש בתפקידי Discord כהרשאה לפקודות מסוימות הם חלקים נפוצים בארכיטקטורה טובה של פקודות בוט. מאז המאזינים שלנו מנוהלים באביב @שֵׁרוּתנוכל בקלות להזריק שעועית אחרת המנוהלת על ידי אביב כדי לטפל במשימות האלה. עם זאת, לא נתמודד עם כל זה במאמר זה.

4.2. EventListener

כדי לקבל הודעות חדשות ממשתמש, עלינו להקשיב ל- MessageCreateEvent. מאז הלוגיקה לעיבוד פקודות כבר חיה MessageListener, אנו יכולים להרחיב אותו כדי לרשת את הפונקציונליות הזו. כמו כן, עלינו ליישם את שלנו EventListener ממשק כדי לעמוד בתכנון הרישום שלנו:

המחלקה הציבורית @Service MessageCreateListener מרחיב את MessageListener מיישמת את EventListener {@Override public Class getEventType () {return MessageCreateEvent.class; } @Override הפעלת מונו ציבורית (אירוע MessageCreateEvent) {return processCommand (event.getMessage ()); }}

באמצעות ירושה, המסר מועבר לשלנו processCommand () שיטה שבה כל האימות והתגובות מתרחשים.

בשלב זה, הבוט שלנו יקבל ויגיב לפקודת "! Todo". עם זאת, אם משתמש מתקן את הפקודה שהוקלטה בצורה שגויה, הבוט לא יגיב. בואו נתמוך במקרה השימוש הזה עם מאזין לאירועים אחר.

4.3. EventListener

ה MessageUpdateEvent נפלט כאשר משתמש עורך הודעה. אנו יכולים להאזין לאירוע זה כדי לזהות פקודות, בדומה לאופן בו אנו מאזינים ל MessageCreateEvent.

לענייננו, אכפת לנו מאירוע זה רק אם תוכן ההודעה שונה. אנו יכולים להתעלם ממופעים אחרים של אירוע זה. למרבה המזל, אנו יכולים להשתמש ב- isContentChanged () שיטה לסינון מקרים כאלה:

@Service בכיתה ציבורית MessageUpdateListener מרחיב את MessageListener מיישם את EventListener {@Override public Class getEventType () {return MessageUpdateEvent.class; } @Override הפעל מונו ציבורי (אירוע MessageUpdateEvent) {החזר Mono.just (אירוע) .filter (MessageUpdateEvent :: isContentChanged) .flatMap (MessageUpdateEvent :: getMessage) .flatMap (super :: processCommand); }}

במקרה זה, מאז getMessage () החזרות מונו במקום גלם הוֹדָעָה, אנחנו צריכים להשתמש flatMap () לשלוח אותו למעמד העל שלנו.

5. בדוק את בוט באי הסכמה

עכשיו שיש לנו בוט דיסקורד מתפקד, אנחנו יכולים להזמין אותו לשרת Discord ולבדוק אותו.

כדי ליצור קישור להזמנה, עלינו לציין אילו הרשאות הבוט דורש כדי לתפקד כראוי. מחשבון הרשאות הרשאות צד שלישי פופולרי משמש לעתים קרובות ליצירת קישור הזמנה עם ההרשאות הדרושות. למרות שזה לא מומלץ לייצור, אנחנו יכולים פשוט לבחור "מנהל מערכת" למטרות בדיקה ולא לדאוג להרשאות האחרות. כל שעליך לעשות הוא לספק את מזהה הלקוח עבור הבוט שלנו (נמצא בפורטל מפתחי Discord) ולהשתמש בקישור שנוצר כדי להזמין את הבוט שלנו לשרת.

אם לא נעניק הרשאות מנהל לבוט, ייתכן שנצטרך לשנות את הרשאות הערוץ כדי שהבוט יוכל לקרוא ולכתוב בערוץ.

הבוט מגיב כעת להודעה "! Todo" וכאשר עורכים הודעה כדי לומר "! Todo":

6. סקירה כללית

מדריך זה תיאר את כל השלבים הדרושים ליצירת בוט דיסקורד באמצעות ספריית Discord4J ו- Spring Boot. לבסוף תואר כיצד להגדיר מבנה פקודה ותגובה מדרגי בסיסי לבוט.

לקבלת בוט שלם ופועל, צפה בקוד המקור ב- GitHub. נדרש אסימון בוט חוקי להפעלתו.