JavaRush /Java Blog /Random-KO /첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 전문적인 성장을 위한 중요성
Pavel Mironov (Miroha)
레벨 16
Москва

첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 전문적인 성장을 위한 중요성

Random-KO 그룹에 게시되었습니다
모두에게 인사드립니다! 자신에 대해 알려주십시오. 저는 24세이고 작년에 기술대학을 졸업했지만 아직 직장 경험이 없습니다. 앞으로는 원래 2019년 가을에 세운 계획에 따르면 2020년 3~4월에 출근하려고 했는데, 아쉽게도 방역이 끼어 모든 것을 중순으로 연기했다고 말씀드리고 싶습니다. -여름, 그리고 앞으로도 나만의 성공 스토리를 써보고 싶다. 첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 1나는 프로그래밍에 끌린 적이 없습니다. 대학에서는 충분한 프로그래밍을 가르쳤지만 당시에는 이 기술에 관심이 없었습니다. 절차적 언어(C), OOP(Java), 데이터베이스, 심지어 어셈블러 및 C++에 대한 1년 과정도 있었습니다. 그러나 솔직히 말해서 나는 가르치는 대부분의 학문이 나에게 쓸모없고보고 목적에만 적합한 것처럼 보였기 때문에 일반적으로 공부에 무관심했습니다 (원칙적으로 그렇습니다). 대학을 졸업한 후 저는 결정을 내려야 했습니다. 기술을 습득하지는 못했지만 일을 해야 했습니다. 나는 자기 교육에 대해 생각해야 했고(오, 나는 이미 멍하니 앉아 있기 때문에 적어도 2년을 놓쳤습니다) 선택은 자연스럽게 Java에 떨어졌습니다. 왜냐하면 대학의 OOP 과정에서 남자 중 한 명이 javarush 과정을 추천했기 때문입니다. , 아시다시피 그는 특히 Java 언어에 전념하고 있습니다. 강의 발표에 관심이 생겼습니다. 네, 그때 저는 프로그래밍을 좋아하지 않았습니다. 어떤 어려움에 직면하면 즉시 포기했고 프로그래밍에는 어려움이 충분했기 때문입니다. 하지만 동시에 코드를 작성하고 싶다는 생각도 들었고, 결국 프로그래밍에 입문하기로 결정했습니다. javarush에 대한 나의 경험에 대해 간략하게 말씀 드리겠습니다. 2019년 8월에 시작해서 즉시 한 달 구독을 구매했는데 레벨 7이 되면서 작업이 어렵다는 것을 깨달았습니다. 나는 코스를 제쳐두고 Shildt를 선택했습니다. 그래서 동시에 3개월 과정을 이수했습니다. 나는 레벨 20(내 두 번째 계정)에 도달했고 Schildt를 거의 완전히 읽은 다음 여기 작업에 지쳐서 나 자신에게 실질적인 이점을 보지 못했습니다. 나는 codewars,leetcode에 가서 비디오 강좌를 보기 시작했습니다. 그건 그렇고, 3개월 만에 저는 "아, 배열이 뭐죠? 어떻게 작업해야 하며 왜 그렇게 무서운가요?"라는 생각을 하게 되었습니다. 컬렉션 클래스(ArrayList, HashMap 등)의 소스 코드에 대한 자세한 연구. 개인적인 경험을 바탕으로 초보자에게 말씀 드리겠습니다. 여기서 가장 중요한 것은 아무것도 이해하지 못하고 아무것도 해결할 수 없을 때 발생하는 느낌을 극복하는 것입니다. 그런 일이 생기면 당신은 모든 것을 포기하고 싶고 이 문제에 대해서는 당신이 너무 어리석은 것 같습니다. 그러한 순간을 자신 안에서 극복하고 정신적으로 휴식을 취하면 성공이 찾아올 것입니다. 많은 사람들이 이에 대처하지 못해서 그러한 노력을 빨리 포기하는 것 같아요. 그 결과 2019년 12월부터 프로젝트에 대해 고민하기 시작했습니다. 텔레그램 봇을 선택하기로 결정했지만 전혀 몰랐습니다. 동시에 한 친구는 자동화하려는 전보에서 자신의 그룹을 위한 기능이 필요했습니다. 그는 내가 프로그래밍을 깊이 공부하고 있다는 것을 알고 나에게 프로젝트를 제안했습니다. 나에게는 경험과 미래의 이력서를 위해, 그 사람을 위해, 그룹의 발전을 위해. 나는 그의 생각을 인용할 수도 있다: "Недавно софтину хотел у программиста заказать, которая загружала бы в выбранное Облако файлы по прямым linkм. Это интересно, так How аналогов нет. И просто очень удобно. Суть: копируешь ссылку, вставляешь в окно и выбираешь нужное Облако (GDrive, Mail, Яндекс Диск и т.п), в своё время софт всё делает на стороне serverа и юзеру ничего не нужно загружать на свою машину (особенно круто, когда у тебя сборка на SSD-накопителях). Думали сделать в web-интерфейсе, чтобы можно было запускать How с телефонов, так и с десктопа... Можно в принципе через приложение реализовать, а не через web-интерфейс. Тебе такое по силам?"저는 일을 시작했지만 결국 며칠 후에 지식 부족으로 인해 아무것도 해결되지 않는다는 것을 깨달았습니다. 친구는 Cloud.Mail에 대한 동일한 링크가 필요했지만 여전히 그렇지 않습니다. API가 없습니다. GDrive를 통해 무언가를 통합하려는 시도가 있었지만 구현이 형편없었고 이 클라우드 서비스는 "고객"에게 적합하지 않았습니다. 처음에는 선택할 수 있는 여러 클라우드를 제공했지만 결국 메일을 제외한 모든 것을 거부했습니다. .ru에 대한 솔루션은 발견되지 않았습니다. 어쨌든 모든 것이 비용이 많이 드는 것으로 판명되었으므로 데이터베이스를 연결하고 스토리지용 서버를 사용하는 등의 작업이 필요했습니다. 그런데 여전히 이 웹 애플리케이션이 필요합니다. 우리를 위해서가 아니라 Google Play 스토어에서 게임 링크를 받고, 링크를 파싱하고, 받은 정보를 라이브러리에 저장한 다음, json 파일로 작성하는 정보봇을 만들기로 결정했습니다. 따라서 요청이 있을 때마다 사용자들의 노력으로 라이브러리가 확장될 수 있으며, 앞으로는 Google Play에 접속하여 편리한 형태로 게임에 대한 정보를 얻을 수 없습니다. /libraryHere_game_name 명령을 작성하고 필요한 모든 것을 얻으세요. 하지만 나중에 말씀드릴 몇 가지 어려움이 있습니다. 처음에는 두 개의 SQL 강좌를 동시에 수강하기 시작하면서 천천히 진행되었습니다. 저는 봇이 어떻게 작동하는지, 그리고 요청을 처리하는 방법을 전혀 이해할 수 없었습니다. 나는 그 프로젝트에 관심이 있는 친구를 만났습니다. 봇의 첫 번째 버전은 약 한 달 만에 준비되었지만 (내 입장에서는) 친구와 의견 차이가 발생했습니다. 나는 봇에서 구문 분석을 담당하는 부분을 맡았고 그는 봇에 대한 요청과 처리 작업을 직접 수행했습니다. 어떤 이유에서인지 그는 봇을 복잡하게 만들고, 일종의 인증을 도입하고, 관리자를 만들고, 불필요한 기능을 추가하기 시작했으며, 저는 그의 코딩 스타일이 별로 마음에 들지 않았습니다. 제 생각에는 이것이 정보봇에서는 필요하지 않은 것 같습니다. 그래서 나는 필요한 기능을 갖춘 봇을 처음부터 직접 작성하기로 결정했습니다. 이제 봇이 실제로 무엇을 하는지 설명하겠습니다(프로젝트 코드의 예를 사용하여). 기사 마지막 부분에 프로젝트의 전체 코드를 첨부할 예정이며, 아쉽게도 이에 대해 완전히 설명할 수는 없습니다. 봇에 전송된 모든 사용자 메시지는 Update 클래스의 개체입니다. 여기에는 많은 정보(메시지 ID, 채팅 ID, 고유 사용자 ID 등)가 포함되어 있습니다. 업데이트에는 문자 메시지, 텔레그램 키보드(콜백)의 응답, 사진, 오디오 등 여러 가지 유형이 있습니다. 사용자가 너무 많은 작업을 하는 것을 방지하기 위해 키보드의 텍스트 요청과 콜백만 처리합니다. 사용자가 사진을 보내면 봇은 해당 사진으로 아무 것도 할 생각이 없음을 알립니다. 기본 봇 클래스의 onUpdateReceived 메서드에서 봇은 업데이트를 받습니다.
@Override
    public void onUpdateReceived(Update update) {
        UpdatesReceiver.handleUpdates(update);
    }
이를 핸들러(자체 UpdatesReceiver 클래스)에 전달합니다.
public static void handleUpdates(Update update) {
        ...
        if (update.hasMessage() && update.getMessage().hasText()){
            log.info("[Update (id {}) типа \"Текстовое сообщение\"]", update.getUpdateId());
            new TextMessageHandler(update, replyGenerator).handleTextMessage();
        }
        else if (update.hasCallbackQuery()) {
            //логгирование
            new CallbackQueryHandler(update, replyGenerator).handleCallBackQuery();
        }
        else {
           //логгирование
            replyGenerator.sendTextMessage(update.getMessage().getChatId(), "Я могу принимать только текстовые messages!");
        }
    }
UpdatesReceiver는 업데이트 유형에 따라 또 다른 특수 핸들러(TextMessageHandler 또는 CallbackQueryHandler)로 제어권을 전송하는 중앙 핸들러입니다. 이 핸들러의 생성자에게 체인 아래로 업데이트를 전달합니다. 업데이트는 봇으로 작업할 때 가장 중요한 것이며 업데이트에 저장된 정보를 사용하여 어떤 사용자와 어떤 채팅에 응답을 보내야 하는지 알아내기 때문에 잃어버릴 수 없습니다. 사용자에게 응답을 생성하기 위해 별도의 클래스를 작성했습니다. 일반 문자 메시지, 인라인 키보드가 있는 메시지, 사진이 있는 메시지, 회신 키보드가 있는 메시지를 보낼 수 있습니다. 인라인 키보드는 다음과 같습니다. 첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 1사용자가 클릭하면 일반 메시지와 거의 동일한 방식으로 처리될 수 있는 콜백을 서버에 보내는 버튼을 정의합니다. 이를 "유지"하려면 자체 핸들러가 필요합니다. 각 버튼에 대한 작업을 설정한 다음 업데이트 개체에 기록합니다. 저것들. "비용" 버튼의 경우 콜백에 대한 설명 "/price"를 설정합니다. 이 설명은 나중에 업데이트에서 얻을 수 있습니다. 다음으로, 별도의 클래스에서 이미 이 콜백을 처리할 수 있습니다.
public void handleCallBackQuery() {
  String call_data = update.getCallbackQuery().getData();
  long message_id = update.getCallbackQuery().getMessage().getMessageId();
  long chat_id = update.getCallbackQuery().getMessage().getChatId();
    switch (call_date){
      case "/price" :
        //тут что-то сделать
        break;
...
응답 키보드는 다음과 같습니다. 첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 2본질적으로 사용자의 입력을 대체합니다. "라이브러리" 버튼을 클릭하면 "라이브러리" 메시지가 봇에 빠르게 전송됩니다. 각 키보드 유형에 대해 빌더 패턴( inlinereply ) 을 구현하는 자체 클래스를 작성했습니다 . 결과적으로 요구 사항에 따라 원하는 키보드를 본질적으로 "그릴" 수 있습니다. 키보드는 다를 수 있지만 원리는 동일하므로 이는 매우 편리합니다. 인라인 키보드를 사용하여 메시지를 보내는 직관적인 방법은 다음과 같습니다.
public synchronized void sendInlineKeyboardMessage(long chat_id, String gameTitle) {
        SendMessage keyboard = InlineKeyboardMarkupBuilder.create(chat_id)
                .setText("Вы может узнать следующую информацию об игре " + gameTitle)
                .row()
                .button("Стоимость " + "\uD83D\uDCB0", "/price " + gameTitle)
                .button("Обновлено " + "\uD83D\uDDD3", "/updated " + gameTitle)
                .button("Версия " + "\uD83D\uDEE0", "/version " + gameTitle)
                .endRow()
                .row()
                .button("Требования " + "\uD83D\uDCF5", "/requirements " + gameTitle)
                .button("Покупки " + "\uD83D\uDED2", "/iap " + gameTitle)
                .button("Размер " + "\uD83D\uDD0E", "/size " + gameTitle)
                .endRow()
                .row()
                .button("Получить всю информацию об игре" + "\uD83D\uDD79", "/all " + gameTitle)
                .endRow()
                .row()
                .button("Скрыть клавиатуру", "close")
                .endRow()
                .build();
        try {
            execute(keyboard);
        } catch (TelegramApiException e) {
            log.error("[Не удалось отправить сообщение с -inline- клавиатурой]: {}", e.getMessage());
        }
    }
봇에 엄격한 기능을 제공하기 위해 /library, /help, /game 등 슬래시 문자를 사용하는 특수 명령이 개발되었습니다. 그렇지 않으면 사용자가 쓸 수 있는 모든 쓰레기를 처리해야 합니다. 실제로 이것이 MessageHandler가 작성된 이유입니다.
if (message.equals(ChatCommands.START.getDescription())) {
     replyGenerator.sendTextMessage(chat_id, new StartMessageHandler().reply());
     replyGenerator.sendReplyKeyboardMessage(chat_id);
}
else if (message.equals(ChatCommands.HELP.getDescription())
             || message.equalsIgnoreCase("Помощь")) {
      replyGenerator.sendTextMessage(chat_id, new HelpMessageHandler().reply());
}
 ...
따라서 봇에 보내는 명령에 따라 특수 핸들러가 작업에 포함됩니다. 더 나아가 파서와 라이브러리의 작업을 살펴보겠습니다. Google Play 스토어의 게임 링크를 봇에 보내면 특수 핸들러가 자동으로 작동합니다 . 이에 대한 응답으로 사용자는 다음 형식으로 게임에 대한 정보를 받게 됩니다. 첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 3동시에 게임을 봇의 라이브러리에 추가하려고 시도하는 메서드가 호출됩니다(먼저 로컬 지도에, 그 다음 -> json 파일에 추가). ). 게임이 이미 라이브러리에 있는 경우 일반 해시맵과 마찬가지로 검사가 수행되며, 필드 데이터(예: 버전 번호가 변경됨)인 경우 라이브러리에 있는 게임을 덮어쓰게 됩니다. 변경 사항이 감지되지 않으면 항목이 작성되지 않습니다. 라이브러리에 게임이 전혀 없으면 먼저 로컬 지도( tyk 와 같은 객체 )에 기록된 다음 json 파일에 기록됩니다. 서버의 애플리케이션이 예기치 않게 닫히면 데이터가 손실되었지만 항상 파일을 사용하여 읽을 수 있습니다. 실제로 프로그램이 시작되면 라이브러리는 항상 정적 블록의 파일에서 처음으로 로드됩니다.
static {
        TypeFactory typeFactory = mapper.getTypeFactory();
        MapType mapType = typeFactory.constructMapType(ConcurrentSkipListMap.class, String.class, GooglePlayGame.class);

        try {
            Path path = Paths.get(LIBRARY_PATH);
            if (!Files.exists(path)) {
                Files.createDirectories(path.getParent());
                Files.createFile(path);
                log.info("[Файл библиотеки создан]");
            }
            else {
                ConcurrentMap<string, googleplaygame=""> temporary = mapper.readValue(new File(LIBRARY_PATH), mapType);
                games.putAll(temporary);
                log.info("[Количество игр в загруженной библиотеке] = " + games.size());
            }
        }
        catch (IOException e) {
            log.error("[Ошибка при чтении/записи file] {}", e.getMessage());
        }
    }
여기에서는 파일에서 게임을 검색할 때 대소문자를 구분하지 않기 위해 추가로 파일의 데이터를 임시 맵으로 읽어야 합니다. 그런 다음 전체 맵으로 "복사"됩니다(tITan QuEST를 작성하면 봇이 계속 라이브러리에 있는 게임 Titan Quest). 다른 솔루션을 찾는 것은 불가능했습니다. 이것이 Jackson을 사용한 역직렬화 기능입니다. 따라서 링크를 요청할 때마다 가능한 경우 게임이 라이브러리에 추가되고 그에 따라 라이브러리가 확장됩니다. 특정 게임에 대한 추가 정보는 /libraryGame_Name 명령을 사용하여 얻을 수 있습니다. 특정 매개변수(예: 현재 버전)와 모든 매개변수를 한 번에 확인할 수 있습니다. 이는 앞서 설명한 인라인 키보드를 사용하여 구현됩니다. 업무를 진행하면서 여기에서 습득한 기술을 적용하면서 문제를 해결하기도 했습니다. 예를 들어, 라이브러리에 있는 임의의 게임 이름 목록(/library 명령을 사용하여 옵션을 사용할 수 있음):
private String getRandomTitles(){
        if (LibraryService.getLibrary().size() < 10){
            return String.join("\n", LibraryService.getLibrary().keySet());
        }
        List<string> keys = new ArrayList<>(LibraryService.getLibrary().keySet());
        Collections.shuffle(keys);
        List<string> randomKeys = keys.subList(0, 10);
        return String.join("\n", randomKeys);
    }
봇은 링크를 어떻게 처리합니까? Google Play(호스트, 프로토콜, 포트)에 속하는지 확인합니다.
private static class GooglePlayCorrectURL {

        private static final String VALID_HOST = "play.google.com";

        private static final String VALID_PROTOCOL = "https";

        private static final int VALID_PORT = -1;

        private static boolean isLinkValid(URI link) {
            return (isHostExist(link) && isProtocolExist(link) && link.getPort() == VALID_PORT);
        }

        private static boolean isProtocolExist(URI link) {
            if (link.getScheme() != null) {
                return link.getScheme().equals(VALID_PROTOCOL);
            }
            else {
                return false;
            }
        }

        private static boolean isHostExist(URI link) {
            if (link.getHost() != null) {
                return link.getHost().equals(VALID_HOST);
            }
            else {
                return false;
            }
        }
모든 것이 정상이면 봇은 Jsoup 라이브러리를 사용하는 링크를 통해 연결됩니다. 이를 통해 추가 분석 및 구문 분석이 필요한 페이지의 HTML 코드를 얻을 수 있습니다. 부정확하거나 유해한 링크로 봇을 속일 수는 없습니다.
if (GooglePlayCorrectURL.isLinkValid(link)){
     if (!link.getPath().contains("apps")){
         throw new InvalidGooglePlayLinkException("К сожалению, бот работает исключительно с играми. Введите другую ссылку.");
     }
     URL = forceToRusLocalization(URL);
     document = Jsoup.connect(URL).get();
 }
     else {
         throw new NotGooglePlayLinkException();
      }
...
여기서 우리는 지역 설정 문제를 해결해야 했습니다. 봇은 유럽에 있는 서버에서 Google Play 스토어에 연결되므로 Google Play 스토어의 페이지가 해당 언어로 열립니다. 나는 페이지의 러시아어 버전으로 "리디렉션"을 강제하는 목발을 작성해야 했습니다(결국 이 프로젝트는 우리 청중을 대상으로 한 것이었습니다). 이렇게 하려면 링크 끝에 Google Play 서버에 대한 GET 요청에 hl: &hl=ru 매개변수를 주의 깊게 추가해야 합니다 .
private String forceToRusLocalization(String URL) {
        if (URL.endsWith("&hl=ru")){
            return URL;
        }
        else {
            if (URL.contains("&hl=")){
                URL = URL.replace(
                        URL.substring(URL.length()-"&hl=ru".length()), "&hl=ru");
            }
            else {
                URL += "&hl=ru";
            }
        }
        return URL;
    }
성공적으로 연결되면 분석 및 구문 분석이 가능한 HTML 문서를 받게 되지만 이는 이 기사의 범위를 벗어납니다. 파서 코드는 여기에 있습니다 . 파서 자체는 필요한 정보를 검색하고 게임을 사용하여 개체를 생성합니다. 이 개체는 나중에 필요한 경우 라이브러리에 추가됩니다. <h2>요약하자면</h2>봇은 특정 기능이 포함된 여러 명령을 지원합니다. 사용자로부터 메시지를 받아 해당 명령과 일치시킵니다. 링크이거나 /game + link 명령인 경우 해당 링크를 확인하여 Google Play에 속하는지 확인합니다. 링크가 맞다면 Jsoup을 통해 접속하여 HTML 문서를 수신합니다. 본 문서는 작성된 파서를 기반으로 분석되었습니다. 게임에 대해 필요한 정보를 문서에서 추출한 다음 게임이 포함된 개체를 이 데이터로 채웁니다. 다음으로, 게임이 있는 개체는 로컬 저장소(게임이 아직 없는 경우)에 배치되고 데이터 손실을 방지하기 위해 즉시 파일에 기록됩니다. 라이브러리에 기록된 게임(게임 이름은 맵의 키, 게임이 포함된 개체는 맵의 값)은 /library Game_name 명령을 사용하여 얻을 수 있습니다. 지정된 게임이 봇의 라이브러리에서 발견되면 사용자는 게임에 대한 정보를 얻을 수 있는 인라인 키보드를 받게 됩니다. 게임을 찾을 수 없는 경우 이름 철자가 올바른지 확인하거나(대소문자를 제외하고 Google Play 스토어의 게임 이름과 완전히 일치해야 함) 봇을 보내 게임을 라이브러리에 추가해야 합니다. 게임 링크. 저는 heroku에 봇을 배포했으며, 나중에 자신만의 봇을 작성하여 heroku에서 무료로 호스팅할 계획을 갖고 있는 사람들을 위해 여러분이 직면할 수 있는 어려움을 해결하기 위한 몇 가지 권장 사항을 제시하겠습니다(제가 직접 접한 이후로). 안타깝게도 Heroku의 특성상 봇 라이브러리는 24시간에 한 번씩 지속적으로 "재설정"됩니다. 내 계획은 Heroku 서버에 파일을 저장하는 것을 지원하지 않으므로 단순히 Github에서 내 게임 파일을 가져옵니다. 여러 가지 해결 방법이 있었습니다. 데이터베이스를 사용하거나 게임과 함께 이 파일을 저장할 다른 서버를 찾는 것입니다. 나는 본질적으로 봇이 그다지 유용하지 않기 때문에 지금은 아무것도 하지 않기로 결정했습니다. 나는 오히려 완전한 경험을 얻기 위해 그것이 필요했고, 그것은 기본적으로 내가 성취한 것입니다. 따라서 Heroku에 대한 권장 사항은 다음과 같습니다.
  1. 러시아에 거주하는 경우 VPN을 사용하여 heroku에 등록해야 할 가능성이 높습니다.

  2. 프로젝트 루트에 Procfile이라는 확장자가 없는 파일을 넣어야 합니다. 내용은 다음과 같아야 합니다: https://github.com/miroha/Telegram-Bot/blob/master/Procfile

  3. pom.xml에서 예제 에 따라 다음 줄을 추가합니다 . 여기서 mainClass 태그는 기본 메서드를 포함하는 클래스에 대한 경로를 나타냅니다. bot.BotApplication(BotApplication 클래스가 봇 폴더에 있는 경우).

  4. mvn package 명령 등을 사용하여 프로젝트를 빌드하지 마십시오. Heroku가 모든 것을 조립해 드립니다.

  5. 프로젝트에 gitignore를 추가하는 것이 좋습니다. 예를 들면 다음과 같습니다.

    # Log file
    *.log
    
    # Compiled resources
    target
    
    # Tests
    test
    
    # IDEA files
    .idea
    *.iml
  6. 실제로 프로젝트를 github에 업로드한 다음 저장소를 Heroku에 연결합니다(또는 다른 방법을 사용합니다. 제가 착각하지 않았다면 그 중 3개가 있습니다).

  7. 다운로드가 성공한 경우("빌드 성공") 반드시 Dynos 구성으로 이동하세요.

    첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 4

    슬라이더를 전환한 다음 ON 위치에 있는지 확인하세요. (내가 이렇게 하지 않았기 때문에 내 봇이 작동하지 않았고 며칠 동안 머리를 쥐어짜며 불필요한 움직임을 많이 했습니다. ).

  8. Github에서 봇 토큰을 숨깁니다. 이렇게 하려면 환경 변수에서 토큰을 가져와야 합니다.

    public class Bot extends TelegramLongPollingBot {
    
        private static final String BOT_TOKEN = System.getenv("TOKEN");
    
        @Override
        public String getBotToken() {
            return BOT_TOKEN;
        }
    ...
    }

    그런 다음 봇을 배포한 후 Heroku 대시보드의 설정 탭에서 이 변수를 설정합니다(TOKEN 오른쪽에 VALUE 필드가 있으므로 거기에 봇의 토큰을 복사하세요).

    첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 5
전체적으로 2개월 동안 내 프로젝트를 진행하면서 나는 다음을 수행했습니다.
  • Java로 작성된 완전히 작동하는 프로젝트를 받았습니다.
  • 타사 API(Telegram Bot API)로 작업하는 방법을 배웠습니다.
  • 실제로 저는 직렬화에 대해 더 깊이 탐구하고 JSON 및 Jackson 라이브러리로 많은 작업을 했습니다(처음에는 GSON을 사용했지만 문제가 있었습니다).
  • 파일 작업 시 기술을 강화하고 Java NIO에 익숙해졌습니다.
  • 구성 .xml 파일 작업 방법을 배웠고 로깅에 익숙해졌습니다.
  • 개발 환경(IDEA)의 숙련도 향상;
  • git으로 작업하는 법을 배우고 gitignore의 가치를 배웠습니다.
  • 웹 페이지 구문 분석 기술을 습득했습니다(Jsoup 라이브러리).
  • 여러 디자인 패턴을 배우고 사용했습니다.
  • 코드 개선에 대한 감각과 욕구를 개발했습니다(리팩토링).
  • 나는 온라인에서 해결책을 찾는 법을 배웠고 답을 찾을 수 없는 질문을 부끄러워하지 않는 법을 배웠습니다.
첫 번째 프로젝트로서의 텔레그램 봇과 개인적인 경험을 바탕으로 한 전문적 성장의 중요성 - 7봇이 얼마나 유용한지, 쓸모 없는지, 코드가 얼마나 예쁘고/못생겼는지 모르겠지만, 제가 얻은 경험은 확실히 그만한 가치가 있었습니다. 나는 내 프로젝트에 대한 책임감을 느꼈다. 때때로 나는 그것을 개선하고 새로운 것을 추가하고 싶습니다. 그것을 실행하고 모든 것이 내가 원하는 대로 작동하는 것을 볼 수 있었을 때, 그것은 정말 스릴이었습니다. 그게 가장 중요한 것 아닌가요? 당신이 하는 일을 즐기고 마지막 초콜릿바처럼 작업하는 모든 코드 라인을 즐겨보세요. 따라서 프로그래밍을 마스터하고 있다면 레벨 40까지 여기에 머물지 말고 가능한 한 빨리 자신의 프로젝트를 시작하라는 조언을 드립니다. 누구든지 관심이 있다면 프로젝트의 소스 코드는 여기에 있습니다(Spring용으로 다시 작성됨): https://github.com/miroha/GooglePlayGames-TelegramBot 지난 두 달 동안 저는 새로운 자료를 거의 공부하지 않았습니다. 내가 막다른 골목에 이르렀다는 사실을. 일을 하지 않으면 다음 달에 할 계획인 Spring Framework를 가르치는 것 외에는 더 이상 어디에서 개발해야 할지 알 수 없습니다. 그런 다음 이 프레임워크를 사용하여 봇을 "다시 작성"해 보겠습니다. 어떤 질문에도 답변할 준비가 되어 있습니다. :) 모두 행운을 빌어 요! 2020년 7월 7일 업데이트 순수 Java로 된 봇이 있는 저장소가 손실되었지만(삭제했고 복사본은 다른 로컬 컴퓨터에 남아 있음) Spring Boot용으로 다시 작성된 봇을 다운로드했습니다: https://github.com/miroha /GooglePlayGames-TelegramBot
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION