Initial commit

This commit is contained in:
Владимир Фёдоров 2022-03-06 01:02:55 +07:00
commit c06ae8317f
14 changed files with 700 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.idea
*.json
/bin
!/config/new_year_config.json

21
LICENSE Normal file
View File

@ -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.

14
README.md Normal file
View File

@ -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> &

19
commands/commands.go Normal file
View File

@ -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")
)

121
config/new_year_config.json Normal file
View File

@ -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": "Если вы идете на новогодний ужин в Греции, по дороге обязательно подберите камень побольше. Крупные камни греки кладут у порога хозяина дома с пожеланиями такого же большого богатства. Если же больших камней не нашлось, можно взять самый маленький и пожелать, чтобы возможные беды хозяев были не тяжелее этого камешка."
}
]
}

7
date/date.go Normal file
View File

@ -0,0 +1,7 @@
package date
import "time"
func Today() int {
return int(time.Now().Weekday())
}

16
go.mod Normal file
View File

@ -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
)

23
go.sum Normal file
View File

@ -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=

135
main.go Normal file
View File

@ -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
}

137
messages/messages.go Normal file
View File

@ -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)
}

View File

@ -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
}

View File

@ -0,0 +1,6 @@
package new_year_service
type NewYearService interface {
GetRandomImageURL() string
GetRandomMessage() NewYearMessage
}

View File

@ -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()
}

118
parser/parser.go Normal file
View File

@ -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
}