Skip to content

Instantly share code, notes, and snippets.

@zo0m
Last active May 2, 2016 17:29
Show Gist options
  • Save zo0m/5672121e2784fe7a406031563db00f3c to your computer and use it in GitHub Desktop.
Save zo0m/5672121e2784fe7a406031563db00f3c to your computer and use it in GitHub Desktop.
moment = require "moment"
crypto = require "crypto"
TelegramBot = require('node-telegram-bot-api')
token = require("./config").token
Place = require "../models/place"
EventType = require "../models/event-type"
Event = require "../models/event"
cache = require "../services/cache"
logger = require "../services/logger/bot"
searcher = require "./searcher"
answerCache = {} #TODO use REDIS, or other caching
getHashFromString = (string)-> hash = crypto.createHash('md5').update(string).digest('hex')
isTodayEvent = (startTime)-> moment.utc(startTime).startOf("day").diff(moment().utc().startOf("day")) is 0
class GOODTelegramBot extends TelegramBot
constructor : (token, opts)->
super token, opts
answerCallbackQuery : (callbackQueryId, text, form = {}) ->
form.callback_query_id = callbackQueryId
form.text = text
@_request 'answerCallbackQuery', {form}
editMessageText : (chatId, messageId, text, form = {}) ->
form.chat_id = chatId
form.message_id = messageId
form.text = text
@_request 'editMessageText', {form}
_processUpdate : (update)->
super update
{message, callback_query} = update
if (not message) and callback_query
this.emit('callback_query', callback_query)
# Setup polling way
bot = new GOODTelegramBot token, polling: true
getEventById = (eventId, methodCacheKey)->
cache.getCacheByQuery methodCacheKey
,
Event
.findOne _id : eventId
.populate "place"
.populate "type"
.populate "photo"
,
cacheTime : 5
generateEventUrl = (eventId)-> "https://go-od.in.ua/event-#{eventId}"
eventToString = (event)->
# console.log "eventToString event : #{JSON.stringify event}"
"""
<b>⚫️ #{event.name}</b>
<b>🕠 #{moment(event.start_time).format "DD MMM в HH:mm"}</b> #{event.type?.name}
<b>#{event.place.name}</b> (#{event.place.address})
#{if event.details?.length then "\n<b>Описание:</b>\n#{event.details?.substr(0, 250)}\n" else "" }
---------
<a href="#{generateEventUrl event.id}">подробнее на go-od.in.ua 🚲</a>
"""
################
bot.onText /\/start/, (msg, match) ->
logger.info "/start : #{JSON.stringify msg}"
options =
parse_mode : "HTML",
reply_markup : {inline_keyboard: [[text: "Добавить бота в чат", switch_inline_query: ""]]}
bot.sendMessage msg.from.id, """
Привет,
Я всего лишь робот для <a href="https://GO-OD.in.ua">GO-OD</a>
Я умею искать ближайшие события в Одессе,
Напиши мне, что тебя интересует, например: "вечеринка"
Еще можешь добавить меня в чат с друзьями и быстро перекидывать им события, или напиши в любом чате, например: "@go_odBot вечеринка"
<b>Скачать приложение</b> для <a href="https://itunes.apple.com/us/app/go-od-kuda-pojti-v-odesse/id1024526139">iOS</a> | <a href="https://play.google.com/store/apps/details?id=go.od.ua">Android</a>
""", options
bot.onText /\/help/, (msg, match) ->
logger.info "/help : #{JSON.stringify msg}"
options =
parse_mode : "HTML",
reply_markup : {inline_keyboard: [[text: "Добавить бота в чат", switch_inline_query: ""]]}
bot.sendMessage msg.from.id, """
Привет,
Я всего лишь робот для <a href="https://GO-OD.in.ua">GO-OD</a>
Я умею искать ближайшие события в Одессе,
Напиши мне, что тебя интересует, например: "вечеринка"
Или команду : "/today"
Еще можешь добавить меня в чат с друзьями и быстро перекидывать им события, или напиши в любом чате, например: "@go_odBot вечеринка"
<b>Скачать приложение</b> для <a href="https://itunes.apple.com/us/app/go-od-kuda-pojti-v-odesse/id1024526139">iOS</a> | <a href="https://play.google.com/store/apps/details?id=go.od.ua">Android</a>
""", options
bot.onText /\/today/, (msg, match) ->
logger.info "/today : #{JSON.stringify msg}"
methodCacheKey = "bot:events:today"
cache.getCacheByQuery methodCacheKey
,
Event
.find()
.where('start_time').gte(moment().startOf("day").utc().format()).lte(moment().endOf("day").utc().format())
.sort start_time : 1
.populate "place"
.populate "type"
.populate "photo"
,
cacheTime : 30
.then (events)->
answer = {
text : "События сегодня: #{moment().format "DD MMM"}"
inline_keyboard : []
}
for event, index in events
if index < 10 #BAD --> Move to query
answer.inline_keyboard.push [
text : "#{moment(event.start_time).format "HH:mm"} | #{event.type.name} | #{event.name} →"
callback_data : "open:event:#{event.id}"
]
answer
.then (answer)->
{text, inline_keyboard} = answer
key = getHashFromString text
answerCache[key] = answer
bot.sendMessage msg.from.id, text, reply_markup : {inline_keyboard}
.then (sended)->
# console.log "sended : #{JSON.stringify sended}"
chatId = sended.chat.id
messageId = sended.message_id
# Any kind of message
#bot.on 'message', (msg) ->
# chatId = msg.chat.id
# console.log "\nmessage got : #{JSON.stringify msg}"
bot.getMe().then (me) ->
console.log 'Hello! My name is %s!', me.first_name
console.log 'My id is %s.', me.id
console.log 'And my username is @%s.', me.username
return
#bot.onText /\/s (.+)/, (msg, match) ->
bot.on 'message', (msg) ->
logger.info "message : #{JSON.stringify msg}"
if msg.text?[0] is "/"
return
query = msg.text
searcher.searchEvent query, moment().utc(), moment().add(14, 'days').endOf("day").utc()
.then (events)->
answer = {
text : "Результат поиска : #{query}"
inline_keyboard : []
}
for event, index in events
startMoment = moment(event.start_time)
dateTimeString = if isTodayEvent(event.start_time) then startMoment.format("HH:mm") else startMoment.format("DD MMM в HH:mm")
answer.inline_keyboard.push [
text : "#{dateTimeString} | #{event.type.name} | #{event.name} →"
callback_data : "open:event:#{event.id}"
]
answer
.then (answer)->
{text, inline_keyboard} = answer
key = getHashFromString text
answerCache[key] = answer
bot.sendMessage msg.from.id, text, reply_markup : {inline_keyboard}
.then (sended)->
# console.log "sended : #{JSON.stringify sended}"
chatId = sended.chat.id
messageId = sended.message_id
bot.on "callback_query", (msg) ->
logger.info "callback_query : #{JSON.stringify msg}"
# console.log "callback_query : #{JSON.stringify msg}"
chatId = msg.message?.chat?.id
messageId = msg.message.message_id
command = (msg.data or "").split ":"
if command?[0] is "back" and answerCache[command?[1]]
answer = answerCache[command?[1]]
{text, inline_keyboard} = answer
bot.editMessageText chatId, messageId, text, reply_markup : {inline_keyboard}
else if (command?[0] is "open") and (command?[1] is "event")
getEventById command?[2], "callback:query:#{msg.data}"
.then (event)->
key = getHashFromString msg.message.text
answer =
text : eventToString(event)
inline_keyboard : [
[
text : "← Назад"
callback_data : "back:#{key}"
]
]
.then (answer)->
{text, inline_keyboard} = answer
bot.editMessageText chatId, messageId, text, reply_markup : {inline_keyboard}, parse_mode : "HTML"
.then (sended)->
console.log "sended : #{JSON.stringify sended}"
chatId = sended.chat.id
messageId = sended.message_id
else
# bot.sendMessage msg.from.id, "Sorry, I didnt understand you. I'm just a robot."
bot.sendMessage msg.from.id, "Прости, я тебя не понял. Я же всего лишь робот."
bot.on "inline_query", (msg) ->
logger.info "inline_query #{JSON.stringify msg}"
q_id = msg.id
methodCacheKey = "bot:inline:query:#{msg.query}"
currentMoment = moment().utc()
endDayUTC = moment().add(7, "days").endOf('day').utc()
searcher.searchEvent msg.query, currentMoment, endDayUTC
.then (events)->
results = []
for event, index in events
startMoment = moment(event.start_time)
dateTimeString = if isTodayEvent(event.start_time) then startMoment.format("HH:mm") else startMoment.format("DD MMM в HH:mm")
results.push
id : "id" + (new Date()).getTime() + event.id
type : "article"
title : "#{dateTimeString} | #{event.type.name} | #{event.name}"
input_message_content :
parse_mode : "HTML"
message_text : eventToString event
results
.then (answer)->
bot.answerInlineQuery q_id, answer
.catch (error)->
bot.answerInlineQuery q_id, []
bot.on 'chosen_inline_result', (msg) ->
console.log 'Chosen:' + msg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment