UdS Fahrplan Bot

UdS Fahrplan Bot

A lightweight Telegram bot designed for Saarland University students — offering fast, clear, and focused public transport information using SaarVV and HAFAS APIs. — Try Now

🔍 What it is

UdS Fahrplan is a minimal alternative to the full Saarfahrplan app. No clutter. No overwhelming options. Just a clean Telegram interface for:

  • 🔄 Trip planning with /trip
  • 🕒 Live departure boards with /depart
  • 🏠 One-tap departures from your home station with /home

Built with students and locals in mind.


✨ Features

  • /trip – Search from A to B in Saarland & Luxembourg
  • /depart – View all upcoming buses from any station
  • /home – Configure your home station and check buses in both directions (e.g., City ↔ Dudweiler)
  • /sethome – Set or update your personal home station
  • Intelligent Filtering – Excludes school buses, allows regional/suburban focus
  • Persistent Storage – Remembers user settings across bot restarts

Read more
UdS Fahrplan Bot Development Log (5) -- Explanations on bot sessions and requests

UdS Fahrplan Bot Development Log (5) -- Explanations on bot sessions and requests

This blog post is trying to tell you:

  • Why session is needed when multiple command using similar workflow?
  • The details of HTTP request
  • Detailed explanations on the implementation of udsfahrbot

Previous post: UdS Fahrplan Bot Development Log (4) – Implementation on /sethome and /home function

Brief Walkthrough on Telegram Bot (Cont.)

In the previous notes, we’ve already implemented all the commands we need! But there’s a question, why we need to format out query in f”{session}:{step}:{loc}”? Also, we haven’t talked about the function that connects to the SaarVV api.

We also have another study notes for all of the telegram bot projects in here, it gives you the basics on how to create your own bot and further descriptions on different functions and attributes on the package python-telegram-bot.

HTTP request on SaarVV

In Application layer, if we send a GET request to the URL, it returns the HTML of the URL. For example:

request.py
1
2
3
4
5
6
7
import requests

try:
res = requests.get("https://greenmeeple.github.io/")
print(res.text)
except Exception as e:
print(f"❌ Error fetching location matches: {e}")

Then we are basically retriving the source code the website.

Read more
UdS Fahrplan Bot Development Log (4) -- Implementation on /sethome and /home function

UdS Fahrplan Bot Development Log (4) -- Implementation on /sethome and /home function

This blog post is trying to tell you:

  • How to build your own telegram bot
  • Detailed explanations on the implementation of udsfahrbot

Previous post: UdS Fahrplan Bot Development Log (3) – Implementation on /trip and /depart function

Brief Walkthrough on Telegram Bot (Cont.)

In the previous notes, we’ve already implemented /trip and /depart based on this. Now, let’s start explaining them one by one.

We also have another study notes for all of the telegram bot projects in here, it gives you the basics on how to create your own bot and further descriptions on different functions and attributes on the package python-telegram-bot.

/sethome – Storing users’ starting station

Similarly, our main function should have app.add_handler(CommandHandler("sethome", spawn)) and InlineKeyboardMarkup[] ready, these components are defined in previous notes and they are reusable.

Next, our function has to be able to distinguish different users. Users who interact with the bot using command or tagged message will have their id stored in message.from_user.id; and query.from_user.id if users are interacting using buttons.

Then, we also need to create a database or storage file to read and write users’ stations. We decide the tool to use based on our use case and needs. Here, the data we need to store are user_id, station_name, and station_id. Which the columns are stable and small size. Therefore, it can be handled by a simple JSON file. Before we store the station, remember to check if the user already stored any station before to avoid creating duplicates.

bot_spawn.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
async def handle_spawn_start(query, context, data):
station = locations[data] if data in locations else data
name = context.user_data.get("spawn_session", {}).get("search_s", {}).get(data, data)
user_id = query.from_user.id

if os.path.exists(SPAWN_DATA):
with open(SPAWN_DATA, "r") as file:
try:
data_list = json.load(file)
except json.JSONDecodeError:
data_list = []
else:
data_list = []

# Check if user already exists
user_found = False
for entry in data_list:
if entry["user_id"] == user_id:
entry["home_id"] = station
entry["home_name"] = name
user_found = True
break

if not user_found:
# Add new user entry
data_list.append({"user_id": user_id, "home_id": station, "home_name": name})

# Save updated data
with open(SPAWN_DATA, "w") as file:
json.dump(data_list, file, indent=2)

await query.edit_message_text(
f"✅ User {user_id}, your home is set to {name:<20}")

async def spawn(update: Update, context: ContextTypes.DEFAULT_TYPE):
context.user_data["spawn_session"] = {}
await update.message.reply_text(f"Hello User {update.message.from_user.id}, Set your spawn point",
reply_markup=build_location_keyboard("spawn","start")
)
Read more
UdS Fahrplan Bot Development Log (3) -- Implementation on /trip and /Depart function

UdS Fahrplan Bot Development Log (3) -- Implementation on /trip and /Depart function

This blog post is trying to tell you:

  • How to build your own telegram bot
  • Detailed explanations on the implementation of udsfahrbot

Previous post: UdS Fahrplan Bot Development Log (2) – Planning for telegram bot

Brief Walkthrough on Telegram Bot

In the previous notes, we’ve talked about our motivation and planned functions we wanted to implement. Now, let’s start explaining them one by one.

We also have another study notes for all of the telegram bot projects in here, it gives you the basics on how to create your own bot and further descriptions on different functions and attributes on the package python-telegram-bot.

We start with the basic trip searching function just like the original app. We used CommandHandler to create the command, InlineKeyboardMarkup to create buttons for stations, CallbackQueryHandler to handle the button actions, and update.message.reply_text to send message back to the users.

bot_trip.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def build_location_keyboard(session, step, exclude=None):
buttons = [
[InlineKeyboardButton(text=loc, callback_data=f"{session}:{step}:{loc}")]
for loc in keyboard_flat if loc != exclude
]
buttons += [[
InlineKeyboardButton(text="More Stations",
callback_data=f"{session}:more:{step}")
]]
if exclude is not None:
buttons += [[
InlineKeyboardButton(text="Back",
callback_data=f"{session}:{step}:back")
]]
return InlineKeyboardMarkup(buttons)

async def trips(update: Update, context: ContextTypes.DEFAULT_TYPE):
context.user_data["trip_session"] = {}

await update.message.reply_text(
"🚌 Choose Your Starting Station.",
reply_markup=build_location_keyboard("trip","start")
)

Buttons for stations and departure time

When the user called the command /trip, the bot will update the message into a list of buttons thanks to the InlineKeyboardMarkup, it passes a string of message with three components, seperated with colon. f”{session}:{step}:{loc}”, it will then pass into handle_callback() and used to indentify different command using session, then it identifies the current state using steps (since stations can be either start or destination), and eventually the station details in loc will be passed to next step.

Read more
UdS Fahrplan Bot Development Log (2) -- Planning for telegram bot

UdS Fahrplan Bot Development Log (2) -- Planning for telegram bot

This blog post is trying to tell you:

  • The motivation of making my own telegram bot
  • Is UdSfahrplan “Reinventing the wheel”?

Saarfahrplan v.s. Uni Students

Previous post: UdS Fahrplan Bot Development Log (1) – Fetching data from HAFAS and its APIs through POST requests

SaarFahrplan is a public transport app to provide real-time information and services related to public transportation in Saarland. Its target users are the people who live and travel in Saarland for general purpose. When it comes to a smaller group of users, for example Uni students, some functionalities might be redundant and we may optimized some common use case for better user experience.

Common use cases for students

Instead of searching different connections, Uni students’ timetable are usually consistent and repetitive. There are a few places where they always go, for example:

  • Go to the Uni
  • Go to the Mensa
  • Go to the Dormintory
  • Go to the City
  • Go to the Supermarket

Another scenario will be when we are in somewhere new, we would like to know how to go back home (dormitory).

Key functions on our telegram bot

Based on the above use case, So we create our own app/bot that only accommodate them.

Read more
UdS Fahrplan Bot Development Log (1) -- Fetching data from HAFAS and its APIs through POST requests

UdS Fahrplan Bot Development Log (1) -- Fetching data from HAFAS and its APIs through POST requests

This blog post is trying to tell you:

  • My personal study notes on HAFAS, a public transport management system used around europe

What is HAFAS?

The HaCon Timetable Information System (HAFAS) is a software for timetable information from the company HaCon (Hannover Consulting). – Wikipedia

Basically, the entire Germany, Luxembourg, and the surrounding countries/regions use HAFAS to obtain depatures and stations details. This centralized software system can be visited using APIs. Different service providers may create their own HAFAS backend endpoint that exposes a public transport API over HTTP for customized usage. For example, you can send your HTTP requests to Deutsche Bahn (DB) if you have the access of their API, which can be found in DB API Marketplace.

What can we do with HAFAS?

There are four basic functions that the system has provided:

  • TripSearch – return connections from location A to location B
  • StationBoard – return all arrivals and departures of a certain station
  • LocGeoPos – return list of stations in a give range of area
  • LocMatch – return list of stations based on the keyword given

These includes most of the functionalities for users. For example, when we tried to plan our journey on DB navigator, the app uses TripSearch to show you connections; when we type the stations in the search box, the app LocMatch to give you related results.

Read more
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×