Initial commit
This commit is contained in:
commit
c06ae8317f
|
@ -0,0 +1,4 @@
|
||||||
|
.idea
|
||||||
|
*.json
|
||||||
|
/bin
|
||||||
|
!/config/new_year_config.json
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 3crabs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,14 @@
|
||||||
|
# student-verochka-bot
|
||||||
|
|
||||||
|
## develop
|
||||||
|
|
||||||
|
git clone https://github.com/3crabs/student-verochka-bot student_bot
|
||||||
|
cd student_bot
|
||||||
|
go run main.go --token=<TELEGRAM_API_TOKEN> --key=<YANDEX_WEATHER_API_KEY>
|
||||||
|
|
||||||
|
## deploy
|
||||||
|
|
||||||
|
git clone https://github.com/3crabs/student-verochka-bot student_bot
|
||||||
|
cd student_bot
|
||||||
|
go build -v -o bin/bot
|
||||||
|
./bin/bot --token=<TELEGRAM_API_TOKEN> --key=<YANDEX_WEATHER_API_KEY> &
|
|
@ -0,0 +1,19 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
type Command string
|
||||||
|
|
||||||
|
//today_lessons - пары сегодня
|
||||||
|
//tomorrow_lessons - пары завтра
|
||||||
|
//weather - погода у универа
|
||||||
|
//new_year - дней до нового года
|
||||||
|
//ping - проверка связи
|
||||||
|
//help - помощь
|
||||||
|
const (
|
||||||
|
Start = Command("/start")
|
||||||
|
Help = Command("/help")
|
||||||
|
Ping = Command("/ping")
|
||||||
|
TodayLessons = Command("/today_lessons")
|
||||||
|
TomorrowLessons = Command("/tomorrow_lessons")
|
||||||
|
Weather = Command("/weather")
|
||||||
|
NewYear = Command("/new_year")
|
||||||
|
)
|
|
@ -0,0 +1,121 @@
|
||||||
|
{
|
||||||
|
"images": [
|
||||||
|
"https://hoteliernews.ru/wp-content/uploads/2018/12/ny.jpg",
|
||||||
|
"https://klike.net/uploads/posts/2020-01/1580460132_37.jpg",
|
||||||
|
"https://ryazan.skidkom.ru/static/content/16417/common/magaziny/16417_15662854534276.jpg",
|
||||||
|
"https://phonoteka.org/uploads/posts/2021-07/1625383153_22-phonoteka-org-p-novogodnie-oboi-na-telefon-uyutnie-oboi-kr-26.jpg",
|
||||||
|
"https://get.wallhere.com/photo/lights-street-cityscape-night-Christmas-holiday-christmas-lights-tree-beauty-gifts-christmas-decoration-699000.jpg",
|
||||||
|
"https://images.unsplash.com/photo-1543589077-870d0ba0a43d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1543200226-409d35b65e09?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1608686977963-8ccdb7ad2284?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1606916929361-b29d5d4a4ad7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1607021145278-5ffe2777fd7e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1576263637347-2aac28621f3d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1512911122913-094837b6fd2f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1606916930054-53ada52915fe?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1577725850396-9793fadbd39f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1608302226718-dd9c4bd1ebe4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1575996301730-435a292f104c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1602522785904-8e03a6d65f4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1577998474517-7eeeed4e448a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1535379665706-aea78de84a41?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1531686264889-56fdcabd163f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1500212802521-de7d7426f496?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1531574840286-d8d45c1dd989?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1514205754505-cde6f571a815?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1451772741724-d20990422508?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1481271134264-c373cb29cf60?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1481366574263-f643ed72bccc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=869&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1607322838027-e692e1e0fc7b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1000&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1578863235656-1330c3081289?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1000&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1576326040690-a4e2968bb3b3?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1887&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1577222959912-2c4ae76903ae?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1609034839396-226723bdf413?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1887&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1576668274938-4cc9da8ee76e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1608478870699-0c4809cccd25?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1886&q=80",
|
||||||
|
"https://images.unsplash.com/photo-1609009755337-df397a1aa480?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1935&q=80",
|
||||||
|
"https://ae01.alicdn.com/kf/HTB1g2gUkoF7MKJjSZFLq6AMBVXah/Laeacco-Kerstboom-Pavilion-Sfeer-Straat-Fotografie-Achtergronden-Vinyl-Custom-Fotografische-Achtergronden-Voor-Fotostudio.jpg"
|
||||||
|
],
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"header": "Мокрый Новый год в Таиланде",
|
||||||
|
"text": "Тайцы очень любят праздники и не отказываются от лишнего повода повеселиться. Возможно, поэтому они отмечают Новый год трижды: европейский новый год, китайский и свой собственный праздник смены года — Сонгкран. Сонгкран празднуется в апреле несколько дней подряд. В это время тайцы выходят на улицы, чтобы пожелать друг другу счастья и... облить водой с головы до ног. Считается, что чем быстрее и сильнее ты промокнешь, тем больше счастья придет в новом году."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Рождественское полено в странах Европы",
|
||||||
|
"text": "Во многих европейских странах существовал обычай в рождественский сочельник зажигать в очаге полено. По традиции, полено должно было тлеть в камине на протяжении нескольких дней. В течение этого времени дерево поливали вином и медом, посыпали зерном и клали на него кусочки еды, чтобы год был плодородным и счастливым. Пепел от полена хранили весь год, добавляя его в еду и напитки от всех болезней. С течением времени эта трудоемкая традиция ушла в прошлое, но в память о ней в некоторых европейских странах едят рождественский торт под названием «Полено»."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "В Новый год с новым именем в Микронезии",
|
||||||
|
"text": "На некоторых островах Микронезии каждый год люди берут себе новое имя. 1 января они нашептывают свое новое имя родственникам и друзьям, при этом бьют в барабан или шумят, чтобы их не подслушали злые духи. Из-за этой традиции часто происходят казусы: однажды половина жителей одного из островов весь год носила имя Майкл Джексон."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Мусорный дождь в новогоднюю ночь в Италии",
|
||||||
|
"text": "В Италии считают, что, вступая в новый год, нужно непременно избавиться от всего старого и ненужного. В канун Нового года темпераментные итальянцы выбрасывают старые вещи прямо из окон своих домов. В былые времена на улицы летела даже сломанная мебель. Сейчас же можно попасть под «обстрел» старыми бумагами и мелким мусором."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "С чемоданом вокруг дома в Эквадоре",
|
||||||
|
"text": "Чтобы год был наполнен множеством путешествий, эквадорцы рекомендуют совершить первое из них прямо в новогоднюю ночь. Для этого нужно обежать вокруг дома с чемоданом в руках, пока часы бьют двенадцать раз."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Виноградины успеха в Испании",
|
||||||
|
"text": "В винных столицах мира ни одно торжество не обходится без винограда. В Испании для всех участников новогоднего застолья заранее подготавливают по двенадцать виноградин (число ударов новогоднего колокола). Испанцы верят, что если все ягоды будут съедены за двенадцать ударов, год обязательно будет успешным."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Гном и битье посуды в Швеции",
|
||||||
|
"text": "В Швеции, в отличие от большинства европейских стран, подарки детям приносит не высокий бородатый старик, а гном Юль Томтен. А помогают ему разные зверюшки, тролли, феи, принц с принцессой и даже Снежная Королева. Шведы очень любят разные гадания. В новогоднюю ночь они разбивают тарелки о двери соседей. Чем мельче осколки, тем больше счастья придет в новом году."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Во Вьетнаме Новый год встречают со стариками",
|
||||||
|
"text": "Вьетнамцы считают, что если за новогодним столом сидит человек старше семидесяти лет, его мудрость распространится на всех присутствующих. И чем старше гость, тем больше почета ему оказывают."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Ожившие сказки Англии и поцелуи под омелой",
|
||||||
|
"text": "Новый год в Англии отмечается традиционным карнавальным шествием, которое возглавляет Лорд Беспорядок. В толпе сказочных героев можно увидеть Мартовского зайца, Шалтая-Болтая и прочих любимцев детей. Дома и улицы Англии украшаются венками из омелы, которая, по поверьям, обладает магической силой. Во время звона новогоднего колокола влюбленные целуются под таким венком, чтобы жить в согласии."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "В Голландии идут в гости со спичками",
|
||||||
|
"text": "Голландцы идут на новогодний ужин, захватив с собой спичку. Спичка впоследствии сжигается в камине. Если она сгорает полностью, год будет очень счастливым."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Бочка дегтя в Шотландии",
|
||||||
|
"text": "В некоторых городах Шотландии в новогоднюю ночь поджигают бочки с дегтем и катят их по улицам города. Так сжигают старый год и очищают дорогу новому. Если вам предстоит новогодний ужин у шотландца, не забудьте захватить с собой уголек, чтобы бросить его в очаг хозяина. Таким образом в Шотландии желают удачи в новом году."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Японцы загребают счастье граблями",
|
||||||
|
"text": "В Японии к Новому году принято украшать дома бамбуковыми граблями. Считается, что если в доме нет граблей, то нечем будет загребать счастье. В первые секунды нового года японцы громко смеются, чтобы год был веселым и радостным."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Во Франции у кого боб, тот и король",
|
||||||
|
"text": "В католической Франции зимние праздники заканчиваются 6 января на Богоявление. Этот праздник посвящен библейскому сюжету о трех волхвах, которые принесли дары младенцу Христу. В современной Франции в этот день едят знаменитый слоеный пирог с начинкой из миндаля — Пирог Волхвов. Пирог разрезается на части, один из гостей забирается под стол и оттуда выкрикивает, кому какой кусок следует отдать. В прежние времена в пироге запекался боб, и человек, которому он попадался, становился королем вечера. Сейчас в пирог кладут керамическую фигурку и корону из картона."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "В Бразилии «море пламенем горит»",
|
||||||
|
"text": "В жаркой Бразилии в новогоднюю ночь океан сверкает огнями. По традиции, люди загадывают желания и пускают по воде плоты со свечами и дарами богине моря. В прибрежные волны бросают лепестки белых цветов в надежде, что океан примет желания и не выбросит лепестки на берег. Приход Нового года сопровождает выстрел из пушки, после которого бразильцы обнимают всех вокруг, чтобы год был полон любви."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "В Венгрии освистывают злых духов",
|
||||||
|
"text": "Венгры уверены в том, что злые духи очень боятся звука свистков и дудочек. Чтобы наступающий год был счастливым, перед его приходом обязательно нужно очистить города от духов-вредителей. И в новогоднюю ночь Венгрия наполняется громкими трелями и свистом."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Чтобы год был сладким, в Израиле едят сладости",
|
||||||
|
"text": "В Израиле отмечают Новый год в сентябре. Во время праздника едят сладкую пищу. Даже рыбу поливают медом. От горькой еды стараются отказаться, чтобы не привлечь «горькую» жизнь в новом году."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Кубинцы смывают грехи в новогоднюю ночь",
|
||||||
|
"text": "В день перед Новым годом на Кубе наливают воду в кружки, тазы и кастрюли. Каждый набирает столько воды, сколько, по его мнению, грехов он совершил за год. После полуночи вода выливается за порог, что символизирует очищение от пороков."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Пауза для поцелуев в Болгарии и кизиловые палочки",
|
||||||
|
"text": "Во время празднования Нового года в Болгарии во всех домах на три минуты выключают свет. В это время можно поцеловаться с тем, с кем не решался сделать это при свете. А 1 января болгарские дети идут поздравлять взрослых с кизиловыми палочками в руках. Дети стучат палочками друг о друга, после чего получают подарки."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Санта Клаус — серфингист в Австралии",
|
||||||
|
"text": "Новый год отмечается в Австралии летом. Жара вынуждает Санту избавиться от теплой шубы, и из всего праздничного костюма на нем часто остаются лишь красные плавки, борода и колпак. Оленям жары тоже не вынести, и на санях без снега не проехать, поэтому Санта Клаус доставляет подарки на серфе. Толпа встречает его на пляже радостными криками и фейерверками."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"header": "Камень за пазухой в Греции",
|
||||||
|
"text": "Если вы идете на новогодний ужин в Греции, по дороге обязательно подберите камень побольше. Крупные камни греки кладут у порога хозяина дома с пожеланиями такого же большого богатства. Если же больших камней не нашлось, можно взять самый маленький и пожелать, чтобы возможные беды хозяев были не тяжелее этого камешка."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package date
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func Today() int {
|
||||||
|
return int(time.Now().Weekday())
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
module student_bot
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/3crabs/go-yandex-weather-api v0.6.0
|
||||||
|
github.com/PuerkitoBio/goquery v1.7.1
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||||
|
github.com/umputun/go-flags v1.5.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
|
||||||
|
)
|
|
@ -0,0 +1,23 @@
|
||||||
|
github.com/3crabs/go-yandex-weather-api v0.6.0 h1:EpqAfaStJNVRNRyYsvUmiNFQYGrQ+eXVP2e+vMWIh08=
|
||||||
|
github.com/3crabs/go-yandex-weather-api v0.6.0/go.mod h1:MZLPelQjylEK4nPL9g2cpnAPtqzOpF/SrtRGWXK7QHs=
|
||||||
|
github.com/PuerkitoBio/goquery v1.7.1 h1:oE+T06D+1T7LNrn91B4aERsRIeCLJ/oPSa6xB9FPnz4=
|
||||||
|
github.com/PuerkitoBio/goquery v1.7.1/go.mod h1:XY0pP4kfraEmmV1O7Uf6XyjoslwsneBbgeDjLYuN8xY=
|
||||||
|
github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
|
||||||
|
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||||
|
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
|
||||||
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||||
|
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||||
|
github.com/umputun/go-flags v1.5.1 h1:vRauoXV3Ultt1HrxivSxowbintgZLJE+EcBy5ta3/mY=
|
||||||
|
github.com/umputun/go-flags v1.5.1/go.mod h1:nTbvsO/hKqe7Utri/NoyN18GR3+EWf+9RrmsdwdhrEc=
|
||||||
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
@ -0,0 +1,135 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"student_bot/commands"
|
||||||
|
"student_bot/date"
|
||||||
|
"student_bot/messages"
|
||||||
|
"student_bot/new_year_service"
|
||||||
|
"student_bot/parser"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
weather "github.com/3crabs/go-yandex-weather-api"
|
||||||
|
tgbot "github.com/go-telegram-bot-api/telegram-bot-api"
|
||||||
|
"github.com/umputun/go-flags"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Opts struct {
|
||||||
|
Token string `short:"t" long:"token" description:"Telegram api token"`
|
||||||
|
Key string `short:"k" long:"key" description:"Yandex weather API key"`
|
||||||
|
Name string `short:"n" long:"name" description:"Telegram bot name" default:"@student_verochka_bot"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var sendMessage = false
|
||||||
|
|
||||||
|
var opts Opts
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
p := flags.NewParser(&opts, flags.PrintErrors|flags.PassDoubleDash|flags.HelpFlag)
|
||||||
|
p.SubcommandsOptional = true
|
||||||
|
if _, err := p.Parse(); err != nil {
|
||||||
|
if err.(*flags.Error).Type != flags.ErrHelp {
|
||||||
|
log.Println(errors.New("[ERROR] cli error: " + err.Error()))
|
||||||
|
}
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
imageService, err := new_year_service.NewNewYearService()
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
imageService = new_year_service.NewNewYearServiceLogWrapper(imageService)
|
||||||
|
|
||||||
|
bot, err := tgbot.NewBotAPI(opts.Token)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
u := tgbot.NewUpdate(0)
|
||||||
|
u.Timeout = 60
|
||||||
|
|
||||||
|
updates, err := bot.GetUpdatesChan(u)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Bot is start up!")
|
||||||
|
|
||||||
|
for update := range updates {
|
||||||
|
|
||||||
|
// empty message
|
||||||
|
if update.Message == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
text := update.Message.Text
|
||||||
|
chatId := update.Message.Chat.ID
|
||||||
|
|
||||||
|
if strings.Contains(strings.ToLower(text), "спасибо") {
|
||||||
|
if sendMessage {
|
||||||
|
_, _ = bot.Send(tgbot.NewMessage(chatId, messages.ThanksMessage()))
|
||||||
|
sendMessage = false
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sendMessage = false
|
||||||
|
|
||||||
|
command := commands.Command(strings.Replace(text, opts.Name, "", 1))
|
||||||
|
switch command {
|
||||||
|
|
||||||
|
case commands.Start:
|
||||||
|
send(bot, tgbot.NewMessage(chatId, messages.StartMessage()))
|
||||||
|
|
||||||
|
case commands.Help:
|
||||||
|
send(bot, tgbot.NewMessage(chatId, messages.HelpMessage()))
|
||||||
|
|
||||||
|
case commands.Ping:
|
||||||
|
send(bot, tgbot.NewMessage(chatId, messages.PongMessage()))
|
||||||
|
|
||||||
|
case commands.TodayLessons:
|
||||||
|
send(bot, tgbot.NewMessage(chatId, messages.LessonsMessage(
|
||||||
|
parser.ParseByDay(date.Today()),
|
||||||
|
"Сегодня, "+update.Message.From.FirstName+", эти пары:",
|
||||||
|
"Сегодня пар нет",
|
||||||
|
)))
|
||||||
|
|
||||||
|
case commands.TomorrowLessons:
|
||||||
|
send(bot, tgbot.NewMessage(chatId, messages.LessonsMessage(
|
||||||
|
parser.ParseByDay(date.Today()+1),
|
||||||
|
"Завтра, "+update.Message.From.FirstName+", эти пары:",
|
||||||
|
"Завтра пар нет",
|
||||||
|
)))
|
||||||
|
|
||||||
|
case commands.Weather:
|
||||||
|
w, err := weather.GetWeatherWithCache(opts.Key, 53.346853, 83.777012, time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
send(bot, tgbot.NewMessage(chatId, messages.WeatherMessage(w)))
|
||||||
|
|
||||||
|
case commands.NewYear:
|
||||||
|
url := imageService.GetRandomImageURL()
|
||||||
|
message := imageService.GetRandomMessage()
|
||||||
|
msg := tgbot.NewPhotoShare(chatId, url)
|
||||||
|
msg.Caption = messages.NewYearMessage(message)
|
||||||
|
send(bot, msg)
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func send(bot *tgbot.BotAPI, msg tgbot.Chattable) {
|
||||||
|
_, _ = bot.Send(msg)
|
||||||
|
sendMessage = true
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
package messages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
weather "github.com/3crabs/go-yandex-weather-api"
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
"student_bot/new_year_service"
|
||||||
|
"student_bot/parser"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartMessage() string {
|
||||||
|
return "Привет, я Верочка!"
|
||||||
|
}
|
||||||
|
|
||||||
|
var thanksMessages = []string{
|
||||||
|
"Обращайся",
|
||||||
|
"Пожалуйста",
|
||||||
|
"Всегда рада помочь",
|
||||||
|
"Да незачто",
|
||||||
|
"Всегда к вашим услугим",
|
||||||
|
}
|
||||||
|
|
||||||
|
func ThanksMessage() string {
|
||||||
|
return thanksMessages[rand.Intn(len(thanksMessages)-1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
func HelpMessage() string {
|
||||||
|
return "Вот чем я могу вам помочь, отправь:\n\n" +
|
||||||
|
"- /ping отобью pong\n" +
|
||||||
|
"- /today_lessons покажу расписание на сегодня\n" +
|
||||||
|
"- /tomorrow_lessons покажу расписание на завтра\n" +
|
||||||
|
"- /weather покажу погоду у универа\n" +
|
||||||
|
"- /new_year - посчитаю количество дней до нового года\n" +
|
||||||
|
"\nНу а больше я пока ничего не умею"
|
||||||
|
}
|
||||||
|
|
||||||
|
func PongMessage() string {
|
||||||
|
return "pong"
|
||||||
|
}
|
||||||
|
|
||||||
|
func LessonsMessage(schedule []parser.Lesson, prefix, emptyText string) string {
|
||||||
|
if len(schedule) == 0 {
|
||||||
|
return emptyText
|
||||||
|
}
|
||||||
|
|
||||||
|
s := ""
|
||||||
|
if prefix != "" {
|
||||||
|
s += prefix + "\n\n"
|
||||||
|
}
|
||||||
|
for _, l := range schedule {
|
||||||
|
if strings.Contains(l.User, "Ярных В.В.") {
|
||||||
|
s += "⭐️ "
|
||||||
|
}
|
||||||
|
s += fmt.Sprintf("%s %s (%s)\n", l.Time, l.Name, l.Place)
|
||||||
|
}
|
||||||
|
if prefix != "" {
|
||||||
|
s += "\n" +
|
||||||
|
"Д — Димитрова 66 (Филологический, социологический)\n" +
|
||||||
|
"Л — Ленина 61 (Математический и биологический)\n" +
|
||||||
|
"М — Ленина 61а (Исторический и географический)\n" +
|
||||||
|
"С — Социалистический 68 (Экономический и юридический)"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func WeatherMessage(w weather.Weather) string {
|
||||||
|
return fmt.Sprintf("Сейчас у универа:\n"+
|
||||||
|
"%s\n"+
|
||||||
|
"Температура: %d°C\n"+
|
||||||
|
"Ощущается как: %d°C\n"+
|
||||||
|
"Скорость ветра: %dм/с\n"+
|
||||||
|
"\nПогода на %s:\n"+
|
||||||
|
"%s\n"+
|
||||||
|
"Температура: %d°C\n"+
|
||||||
|
"Ощущается как: %d°C\n"+
|
||||||
|
"Скорость ветра: %dм/с\n",
|
||||||
|
w.Fact.GetCondition(),
|
||||||
|
w.Fact.Temp,
|
||||||
|
w.Fact.FeelsLike,
|
||||||
|
w.Fact.WindSpeed,
|
||||||
|
w.Forecast.Parts[0].GetPartName(),
|
||||||
|
w.Forecast.Parts[0].GetCondition(),
|
||||||
|
w.Forecast.Parts[0].TempAvg,
|
||||||
|
w.Forecast.Parts[0].FeelsLike,
|
||||||
|
w.Forecast.Parts[0].WindSpeed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewYearMessage(message new_year_service.NewYearMessage) string {
|
||||||
|
loc := time.FixedZone("UTC+7", +7*60*60)
|
||||||
|
ny := time.Date(2023, 1, 1, 0, 0, 0, 0, loc)
|
||||||
|
now := time.Now().In(loc)
|
||||||
|
days := ny.Sub(now).Hours() / 24
|
||||||
|
return fmt.Sprintf("❄ %s ❄ \n\n%s\n\n%s", toStrDays(int(days)), message.Header, message.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toStrDays(days int) string {
|
||||||
|
if days == 0 {
|
||||||
|
return "Сегодня новый год!!!"
|
||||||
|
}
|
||||||
|
if days == 1 {
|
||||||
|
return "Новый год завтра!"
|
||||||
|
}
|
||||||
|
s := ""
|
||||||
|
a := days % 10
|
||||||
|
if days < 10 {
|
||||||
|
switch a {
|
||||||
|
case 2:
|
||||||
|
s = "дня"
|
||||||
|
case 3:
|
||||||
|
s = "дня"
|
||||||
|
case 4:
|
||||||
|
s = "дня"
|
||||||
|
default:
|
||||||
|
s = "дней"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if days >= 10 && days < 20 {
|
||||||
|
s = "дней"
|
||||||
|
}
|
||||||
|
if days >= 20 {
|
||||||
|
switch a {
|
||||||
|
case 1:
|
||||||
|
s = "день"
|
||||||
|
case 2:
|
||||||
|
s = "дня"
|
||||||
|
case 3:
|
||||||
|
s = "дня"
|
||||||
|
case 4:
|
||||||
|
s = "дня"
|
||||||
|
default:
|
||||||
|
s = "дней"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("До нового года %d %s", days, s)
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package new_year_service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type newYearConfig struct {
|
||||||
|
Images []string `json:"images"`
|
||||||
|
Messages []NewYearMessage `json:"messages"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewYearMessage struct {
|
||||||
|
Header string `json:"header"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type newYearService struct {
|
||||||
|
images []string
|
||||||
|
messages []NewYearMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNewYearService() (NewYearService, error) {
|
||||||
|
images, messages, err := readImagesFromConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &newYearService{images: images, messages: messages}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *newYearService) GetRandomImageURL() string {
|
||||||
|
return is.images[rand.Intn(len(is.images))]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is *newYearService) GetRandomMessage() NewYearMessage {
|
||||||
|
return is.messages[rand.Intn(len(is.messages))]
|
||||||
|
}
|
||||||
|
|
||||||
|
func readImagesFromConfig() ([]string, []NewYearMessage, error) {
|
||||||
|
file, err := os.Open("config/new_year_config.json")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
_ = file.Close()
|
||||||
|
}(file)
|
||||||
|
bytes, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
newYearConfig := &newYearConfig{}
|
||||||
|
if err := json.Unmarshal(bytes, newYearConfig); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return newYearConfig.Images, newYearConfig.Messages, nil
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package new_year_service
|
||||||
|
|
||||||
|
type NewYearService interface {
|
||||||
|
GetRandomImageURL() string
|
||||||
|
GetRandomMessage() NewYearMessage
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package new_year_service
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
type newYearServiceLogWrapper struct {
|
||||||
|
service NewYearService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNewYearServiceLogWrapper(service NewYearService) NewYearService {
|
||||||
|
return &newYearServiceLogWrapper{service: service}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *newYearServiceLogWrapper) GetRandomImageURL() string {
|
||||||
|
log.Println("get random image url")
|
||||||
|
return w.service.GetRandomImageURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *newYearServiceLogWrapper) GetRandomMessage() NewYearMessage {
|
||||||
|
log.Println("get random message")
|
||||||
|
return w.service.GetRandomMessage()
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Lesson struct {
|
||||||
|
Day int
|
||||||
|
Number string
|
||||||
|
Time string
|
||||||
|
Name string
|
||||||
|
User string
|
||||||
|
Place string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseByDay(day int) []Lesson {
|
||||||
|
return selectLessonsByDay(parse(), day)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse() []Lesson {
|
||||||
|
url := "https://www.asu.ru/timetable/students/12/2129440415/"
|
||||||
|
|
||||||
|
// Get html
|
||||||
|
res, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
_ = Body.Close()
|
||||||
|
}(res.Body)
|
||||||
|
if res.StatusCode != 200 {
|
||||||
|
log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the HTML document
|
||||||
|
doc, err := goquery.NewDocumentFromReader(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the review items
|
||||||
|
k := 0
|
||||||
|
var lessons []Lesson
|
||||||
|
var l Lesson
|
||||||
|
doc.Find(".schedule tr>td, .schedule tr>td[width=\"100%\"]").Each(func(i int, s *goquery.Selection) {
|
||||||
|
text := strings.TrimSpace(s.Text())
|
||||||
|
if strings.Contains(text, "Понедельник") ||
|
||||||
|
strings.Contains(text, "Вторник") ||
|
||||||
|
strings.Contains(text, "Среда") ||
|
||||||
|
strings.Contains(text, "Четверг") ||
|
||||||
|
strings.Contains(text, "Пятница") ||
|
||||||
|
strings.Contains(text, "Суббота") {
|
||||||
|
k = 0
|
||||||
|
l = Lesson{}
|
||||||
|
if strings.Contains(text, "Понедельник") {
|
||||||
|
l.Day = 1
|
||||||
|
}
|
||||||
|
if strings.Contains(text, "Вторник") {
|
||||||
|
l.Day = 2
|
||||||
|
}
|
||||||
|
if strings.Contains(text, "Среда") {
|
||||||
|
l.Day = 3
|
||||||
|
}
|
||||||
|
if strings.Contains(text, "Четверг") {
|
||||||
|
l.Day = 4
|
||||||
|
}
|
||||||
|
if strings.Contains(text, "Пятница") {
|
||||||
|
l.Day = 5
|
||||||
|
}
|
||||||
|
if strings.Contains(text, "Суббота") {
|
||||||
|
l.Day = 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n := (k - 1) % 6
|
||||||
|
if n == 0 {
|
||||||
|
l.Number = trim(text)
|
||||||
|
}
|
||||||
|
if n == 1 {
|
||||||
|
l.Time = trim(text)
|
||||||
|
}
|
||||||
|
if n == 2 {
|
||||||
|
l.Name = trim(text)
|
||||||
|
}
|
||||||
|
if n == 3 {
|
||||||
|
l.User = trim(text)
|
||||||
|
}
|
||||||
|
if n == 4 {
|
||||||
|
l.Place = trim(text)
|
||||||
|
if l.Place == "" {
|
||||||
|
l.Place = "не приходи"
|
||||||
|
}
|
||||||
|
lessons = append(lessons, l)
|
||||||
|
}
|
||||||
|
k++
|
||||||
|
})
|
||||||
|
return lessons
|
||||||
|
}
|
||||||
|
|
||||||
|
func trim(s string) string {
|
||||||
|
s = strings.Replace(s, "пр.з.", "пр.", -1)
|
||||||
|
s = strings.Replace(s, " ", "", -1)
|
||||||
|
s = strings.Replace(s, "\n", " ", -1)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func selectLessonsByDay(schedule []Lesson, day int) []Lesson {
|
||||||
|
var todayLessons []Lesson
|
||||||
|
for _, l := range schedule {
|
||||||
|
if l.Day == day {
|
||||||
|
todayLessons = append(todayLessons, l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return todayLessons
|
||||||
|
}
|
Loading…
Reference in New Issue