From 99c5a25aedd513757aa39fbe0daa76a088e82dc3 Mon Sep 17 00:00:00 2001 From: Shrimadhav U K Date: Thu, 18 Oct 2018 19:23:54 +0530 Subject: [PATCH] Make Heroku button compatible. 1. The webhook should listen to 0.0.0.0 on heroku. (Ref: https://t.me/MarieSupport/87791) 2. Created app.json (This can make deploying the application as simple as https://heroku.com/deploy?template=LINK_TOGIT_REPO ) 3. Created Procfile to know which process to be run as a web process. 4. Removed configparser as a dependency --- Procfile | 1 + RailwayStatus.py | 315 +++++++++++++++++++++++++++-------------------- app.json | 34 +++++ sample_config.py | 10 ++ 4 files changed, 225 insertions(+), 135 deletions(-) create mode 100644 Procfile create mode 100644 app.json create mode 100644 sample_config.py diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..2d4815a --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: python3 RailwayStatus.py diff --git a/RailwayStatus.py b/RailwayStatus.py index 708730d..16fea24 100644 --- a/RailwayStatus.py +++ b/RailwayStatus.py @@ -1,4 +1,7 @@ -stationcode=""" +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +stationcode = """ ALLP Alappuzha AWY Aluva CLT Calicut @@ -20,9 +23,9 @@ TCR Trichur TVC Trivandrum Central KCVL Trivandrum Kochuveli - + -------------outside kerala-------------- - + Chennai Central (MAS) Chennai Egmore (MS) Bangalore Cy Junction (SBC) @@ -36,15 +39,15 @@ Kolkata (CP) Srinagar (SNAR) Kanyakumari (CAPE) -Patna Junction (PNBE) +Patna Junction (PNBE) """ HELP_TEXT = """ what this bot can do ..? this bot helps to get services offered by NTES - maintained by @prinzpiuz - for more news subscribe to my channel @princepiuz - for help please enter /help + maintained by @prinzpiuz + for more news subscribe to my channel @princepiuz + for help please enter /help source code is available @ https://github.com/prinzpiuz/RailwayStatusBot suggetions and contributions are always welcome @@ -57,122 +60,152 @@ filename="Rail.log", level=logging.INFO, format="%(asctime)s:%(levelname)s:%(message)s" - ) -import configparser +) + import urllib3 import json import time import datetime from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, InlineQueryResultArticle, InputTextMessageContent, ParseMode from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, InlineQueryHandler -config = configparser.RawConfigParser() -config.read('rail.cfg') -token=config.get('telegram','token') -key=config.get('railwayAPI','key') -logging.info(key) -logging.info(token) + +import os +# the secret configuration specific things +ENV = bool(os.environ.get("IS_WEBHOOK", False)) +if ENV: + from sample_config import Config +else: + from config import Config + +# config = configparser.RawConfigParser() +# config.read('rail.cfg') +# token = config.get('telegram', 'token') +# key = config.get('railwayAPI', 'key') +# logging.info(key) +# logging.info(token) + +token = Config.TG_BOT_TOKEN +key = Config.RAIL_WAY_API_TOKEN + + def start(bot, update): update.message.reply_text(HELP_TEXT) + + def trains(bot, update, args): - if len(args)==2: - text="trains between " +args[0]+ " and " +args[1]+" are............." - date=datetime.datetime.today().strftime('%d-%m-%Y') + if len(args) == 2: + text = "trains between " + args[0] + \ + " and " + args[1] + " are............." + date = datetime.datetime.today().strftime('%d-%m-%Y') http = urllib3.PoolManager() - api="https://api.railwayapi.com/v2/between/source/"+args[0]+"/dest/"+args[1]+"/date/"+date+"/apikey/"+key+"/" + api = "https://api.railwayapi.com/v2/between/source/" + \ + args[0] + "/dest/" + args[1] + "/date/" + \ + date + "/apikey/" + key + "/" logging.info(api) r = http.request('GET', api) data = json.loads(r.data.decode('utf-8')) if data['response_code'] != 200: - alert=""" alert ....! are you sure with short codes of station you entered ??? + alert = """ alert ....! are you sure with short codes of station you entered ??? if you have doubt please use /code """ - update.message.reply_text(alert) + update.message.reply_text(alert) else: - - update.message.reply_text(text) + + update.message.reply_text(text) # logging.info(len(data['trains'])) - for i in range(0,len(data['trains'])): - update.message.reply_text("""train named """+data['trains'][i]['name']+" with train number: #"+data['trains'][i]['number']+""" - from """+data['trains'][i]['from_station']['name']+ - """ to """+ data['trains'][i]['to_station']['name']+ """ - starting at """+data['trains'][i]['src_departure_time']+" and arriving at "+data['trains'][i]['dest_arrival_time']+""" - total travel time is:"""+data['trains'][i]['travel_time']) - + for i in range(0, len(data['trains'])): + update.message.reply_text("""train named """ + data['trains'][i]['name'] + " with train number: #" + data['trains'][i]['number'] + """ + from """ + data['trains'][i]['from_station']['name'] + + """ to """ + data['trains'][i]['to_station']['name'] + """ + starting at """ + data['trains'][i]['src_departure_time'] + " and arriving at " + data['trains'][i]['dest_arrival_time'] + """ + total travel time is:""" + data['trains'][i]['travel_time']) + # logging.info(data['trains'][i]['to_station']) # logging.info(data['trains'][i]['from_station']) - + # update.message.reply_text(data['trains'][i]) elif len(args) < 2: - less="need start and destination" + less = "need start and destination" update.message.reply_text(less) update.message.reply_text(help) else: - great="only need start and destination" + great = "only need start and destination" update.message.reply_text(great) update.message.reply_text(help) # text="trains between " +args[0]+ " and " +args[1]+" updating soon" - # update.message.reply_text(text) + # update.message.reply_text(text) + + def date(bot, update, args): - if len(args)==5: - textdate="trains between " +args[0]+ " and " +args[1]+" on date "+args[2]+"-"+args[3]+"-"+args[4]+" are............." - #logging.info(text) + if len(args) == 5: + textdate = "trains between " + args[0] + " and " + args[1] + \ + " on date " + args[2] + "-" + args[3] + \ + "-" + args[4] + " are............." + # logging.info(text) http = urllib3.PoolManager() - apidate="https://api.railwayapi.com/v2/between/source/"+args[0]+"/dest/"+args[1]+"/date/"+args[2]+"-"+args[3]+"-"+args[4]+"/apikey/"+key+"/" + apidate = "https://api.railwayapi.com/v2/between/source/" + \ + args[0] + "/dest/" + args[1] + "/date/" + args[2] + \ + "-" + args[3] + "-" + args[4] + "/apikey/" + key + "/" logging.info(apidate) r = http.request('GET', apidate) data = json.loads(r.data.decode('utf-8')) if data['response_code'] != 200: - alert=""" alert ....! are you sure with short codes of station you entered and the date format ??? - if you have doubt please use /code + alert = """ alert ....! are you sure with short codes of station you entered and the date format ??? + if you have doubt please use /code and date format is dd mm yyyy like 08 09 2018 """ - update.message.reply_text(alert) + update.message.reply_text(alert) else: - - update.message.reply_text(textdate) + + update.message.reply_text(textdate) # logging.info(len(data['trains'])) - for i in range(0,len(data['trains'])): - update.message.reply_text("""train named """+data['trains'][i]['name']+" with train number: "+data['trains'][i]['number']+""" - from """+data['trains'][i]['from_station']['name']+ - """ to """+ data['trains'][i]['to_station']['name']+ """ - starting at """+data['trains'][i]['src_departure_time']+" and arriving at "+data['trains'][i]['dest_arrival_time']+""" - total travel time is:"""+data['trains'][i]['travel_time'],parse_mode=ParseMode.HTML) - + for i in range(0, len(data['trains'])): + update.message.reply_text("""train named """ + data['trains'][i]['name'] + " with train number: " + data['trains'][i]['number'] + """ + from """ + data['trains'][i]['from_station']['name'] + + """ to """ + data['trains'][i]['to_station']['name'] + """ + starting at """ + data['trains'][i]['src_departure_time'] + " and arriving at " + data['trains'][i]['dest_arrival_time'] + """ + total travel time is:""" + data['trains'][i]['travel_time'], parse_mode=ParseMode.HTML) + # logging.info(len(data['trains'])) - + elif len(args) < 5: - less="""need start and destination and date in dd-mm-yyyy + less = """need start and destination and date in dd-mm-yyyy eg: /date awy sbc 15 08 2018 """ update.message.reply_text(less) update.message.reply_text(help) else: - great=""""only need start, destination and date + great = """"only need start, destination and date eg: /date awy sbc 15 08 2018""" update.message.reply_text(great) update.message.reply_text(help) + + def code(bot, update): update.message.reply_text(stationcode) + + def pnr(bot, update, args): http = urllib3.PoolManager() # print(args[0]) - PNR="https://api.railwayapi.com/v2/pnr-status/pnr/"+args[0]+"/apikey/"+key+"/" + PNR = "https://api.railwayapi.com/v2/pnr-status/pnr/" + \ + args[0] + "/apikey/" + key + "/" logging.debug(PNR) r = http.request('GET', PNR) data = json.loads(r.data.decode('utf-8')) if data['response_code'] != 200: - alertp="are you sure with your PNR no "+args[0]+" ?" + alertp = "are you sure with your PNR no " + args[0] + " ?" update.message.reply_text(alertp) else: update.message.reply_text("processing .........") - msg="""your status for PNR no """+args[0]+""" for journey starting from - """+ data['boarding_point']['name']+ """ to """+data['reservation_upto']['name']+""" - in train """+data['train']['name']+""" with no """+data['train']['number']+""" - in """+ data['journey_class']['name']+"""with following people bellow.""" + msg = """your status for PNR no """ + args[0] + """ for journey starting from + """ + data['boarding_point']['name'] + """ to """ + data['reservation_upto']['name'] + """ + in train """ + data['train']['name'] + """ with no """ + data['train']['number'] + """ + in """ + data['journey_class']['name'] + """with following people bellow.""" update.message.reply_text(msg) - for i in range(0,len(data['passengers'])): - print(len(data['passengers'])) - update.message.reply_text(""" - person """ +data['passenger'][i]['no']+""". current status: """+data['passenger'][i]['current_status']+""" - and booking status: """+data['passenger'][i]['booking_status']) + for i in range(0, len(data['passengers'])): + print(len(data['passengers'])) + update.message.reply_text(""" + person """ + data['passenger'][i]['no'] + """. current status: """ + data['passenger'][i]['current_status'] + """ + and booking status: """ + data['passenger'][i]['booking_status']) def live(bot, update, args): @@ -186,7 +219,7 @@ def live(bot, update, args): update.message.reply_text( 'only need train number and date ' 'eg: /live 12046 01-12-2018' - ) + ) else: # for now we won't implement a date validator LIVE = ( @@ -194,11 +227,11 @@ def live(bot, update, args): '/train/{train_number}' '/date/{date}' '/apikey/{key}' - ).format( - train_number=train_number, - date=date, - key=key - ) + ).format( + train_number=train_number, + date=date, + key=key + ) r = http.request('GET', LIVE) data = json.loads(r.data.decode('utf-8')) if data['response_code'] != 200: @@ -210,12 +243,13 @@ def live(bot, update, args): msg = ( 'Train: {name}\n' 'Status: {position}' - ).format( - name=train_name, - position=position - ) + ).format( + name=train_name, + position=position + ) update.message.reply_text(msg) + def arrivals(bot, update, args): """Gives list of trains arriving at a station within a window period, along with their live status. @@ -229,7 +263,7 @@ def arrivals(bot, update, args): 'only need station code and hours window' 'eg: /arrivals sbc 2' 'eg: /arrivals awy 4' - ) + ) else: # for now we won't implement a date validator LIVE = ( @@ -237,11 +271,11 @@ def arrivals(bot, update, args): '/station/{station}' '/hours/{hours}' '/apikey/{key}' - ).format( - station=station_code, - hours=hrs, - key=key - ) + ).format( + station=station_code, + hours=hrs, + key=key + ) r = http.request('GET', LIVE) data = json.loads(r.data.decode('utf-8')) if data['response_code'] != 200: @@ -251,20 +285,21 @@ def arrivals(bot, update, args): arriving_trains = data['trains'] total_trains = data['total'] if arriving_trains: - msg = "Total {} trains arriving during {}".format(total_trains,hrs) + msg = "Total {} trains arriving during {}".format( + total_trains, hrs) update.message.reply_text(msg) for arr_train in arriving_trains: train_name = arr_train["name"] train_number = arr_train["number"] - + sch_arr = arr_train["scharr"] act_arr = arr_train["actarr"] delay_arr = arr_train["delayarr"] - + sched_dep = arr_train["schdep"] act_dep = arr_train["actdep"] delay_dep = arr_train["delaydep"] - + msg = ( 'Train: {name}\n' 'Train Number: {number}\n' @@ -274,25 +309,26 @@ def arrivals(bot, update, args): 'Scheduled Departure: {schdep}\n' 'Actual Departure: {actdep}\n' 'Delay in Departure: {delaydep}' - ).format( - name = train_name, - number = train_number, - scharr = sch_arr, - actarr = act_arr, - delayarr = delay_arr, - schdep = sched_dep, - actdep = act_dep, - delaydep = delay_dep - ) + ).format( + name=train_name, + number=train_number, + scharr=sch_arr, + actarr=act_arr, + delayarr=delay_arr, + schdep=sched_dep, + actdep=act_dep, + delaydep=delay_dep + ) update.message.reply_text(msg) else: alert = "No arriving trains during {} hours".format(hrs) update.message.reply_text(alert) + def seats(bot, update, args): """ Get train seats availability. - Required args are Train Number, Source Stn Code, + Required args are Train Number, Source Stn Code, Destination Stn Code, Journey Date, Pref Code, Quota Code """ http = urllib3.PoolManager() @@ -302,7 +338,7 @@ def seats(bot, update, args): update.message.reply_text( 'Need Train Number, Source Stn Code, Destination Stn Code, Journey Date, Pref Code, Quota Code' 'eg: /seats 12017 NDLS DDN 18-10-2018 CC GN' - ) + ) else: # for now we won't implement a date validator LIVE = ( @@ -314,18 +350,18 @@ def seats(bot, update, args): '/pref/{pref_code}' '/quota/{quota_code}' '/apikey/{key}' - ).format( - train=train_name, - src_station=src_stn_code, - dest_station=dest_stn_code, - jourey_date=journey_date, - pref_code=pref, - quota_code=quota, - key=key - ) + ).format( + train=train_name, + src_station=src_stn_code, + dest_station=dest_stn_code, + jourey_date=journey_date, + pref_code=pref, + quota_code=quota, + key=key + ) r = http.request('GET', LIVE) data = json.loads(r.data.decode('utf-8')) - + if data['response_code'] != 200: alert = "something went wrong" update.message.reply_text(alert) @@ -336,41 +372,41 @@ def seats(bot, update, args): quota_name = data['quota']['name'] train_name = data['train']['name'] availability = data['availability'] - availability_status_combn = {avl['date']:avl['status'] for avl in availability} - availability_str = str(availability_status_combn).replace('{','')\ - .replace('}','')\ - .replace("'",'')\ - .replace(',','\n') + availability_status_combn = { + avl['date']: avl['status'] for avl in availability} + availability_str = str(availability_status_combn).replace('{', '')\ + .replace('}', '')\ + .replace("'", '')\ + .replace(',', '\n') msg = ( - 'Train Name : {name}\n' - 'From : {source}\n' - 'To : {dest}\n' - 'Class : {pref}\n' - 'Quota : {quota}\n' - 'Availability: \n' - '{availability}' - ).format( - name=train_name, - source=src_stn_name, - dest=dest_stn_name, - pref=journey_class_name, - quota=quota_name, - availability=availability_str - ) + 'Train Name : {name}\n' + 'From : {source}\n' + 'To : {dest}\n' + 'Class : {pref}\n' + 'Quota : {quota}\n' + 'Availability: \n' + '{availability}' + ).format( + name=train_name, + source=src_stn_name, + dest=dest_stn_name, + pref=journey_class_name, + quota=quota_name, + availability=availability_str + ) update.message.reply_text(msg) def help(bot, update): - help = """ - available commands and their usage - for listings trains between stations use + available commands and their usage + for listings trains between stations use /trains - eg: for travelling from aluva to banglore enter + eg: for travelling from aluva to banglore enter /trains awy sbc - for listing short station codes + for listing short station codes /code for listing trains on particular date /date
@@ -387,20 +423,29 @@ def help(bot, update): """ update.message.reply_text(help) + + def main(): updater = Updater(token) j = updater.job_queue dp = updater.dispatcher dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("trains", trains, pass_args=True)) - dp.add_handler(CommandHandler("date",date, pass_args=True)) + dp.add_handler(CommandHandler("date", date, pass_args=True)) dp.add_handler(CommandHandler("help", help)) - dp.add_handler(CommandHandler("code",code)) - dp.add_handler(CommandHandler("pnr",pnr,pass_args=True)) + dp.add_handler(CommandHandler("code", code)) + dp.add_handler(CommandHandler("pnr", pnr, pass_args=True)) dp.add_handler(CommandHandler("live", live, pass_args=True)) dp.add_handler(CommandHandler("arrivals", arrivals, pass_args=True)) dp.add_handler(CommandHandler("seats", seats, pass_args=True)) - updater.start_polling() + if ENV: + updater.start_webhook( + listen="0.0.0.0", port=Config.PORT, url_path=Config.TG_BOT_TOKEN) + updater.bot.set_webhook(url=Config.URL + Config.TG_BOT_TOKEN) + else: + updater.start_polling() updater.idle() + + if __name__ == '__main__': main() diff --git a/app.json b/app.json new file mode 100644 index 0000000..ca41f16 --- /dev/null +++ b/app.json @@ -0,0 +1,34 @@ +{ + "name": "RailGadiBot", + "description": "This is Telegram Bot which helps to get the services offered by NTES", + "keywords": [ + "telegram", + "3", + "train", + "railway", + "api" + ], + "repository": "https://github.com/prinzpiuz/RailwayStatusBot", + "env": { + "IS_WEBHOOK": { + "description": "Setting this to ANYTHING will enable webhook. But, you need to understand the code to know what to set here!", + "value": "True" + }, + "TG_BOT_TOKEN": { + "description": "Your bot token, as a string.", + "value": "" + }, + "URL": { + "description": "The Heroku App URL similar to https://.herokuapp.com/", + "value": "" + }, + "PORT": { + "description": "Port to use for your webhooks", + "value": "8443" + }, + "RAIL_WAY_API_TOKEN": { + "description": "Get a token from railwayapi.com", + "value": "" + } + } +} diff --git a/sample_config.py b/sample_config.py new file mode 100644 index 0000000..2f61ed5 --- /dev/null +++ b/sample_config.py @@ -0,0 +1,10 @@ +import os + +class Config(object): + # get a token from @BotFather + TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", None) + # required for running on Heroku + URL = os.environ.get("URL", "") + PORT = int(os.environ.get("PORT", 5000)) + # get a token from railwayapi.com + RAIL_WAY_API_TOKEN = os.environ.get("RAIL_WAY_API_TOKEN", None)