Skip to content

Commit

Permalink
refactor-config
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammad Shafiee committed Aug 9, 2024
1 parent 1b5c312 commit c7faf46
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 136 deletions.
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ COPY --from=builder /app/webBridgeBot /app/webBridgeBot
# Copy the run script
COPY run.sh /app/run.sh

# Copy the run templates
COPY templates /app/templates

# Set the permissions for the binary and the run script
RUN chmod +x /app/webBridgeBot
RUN chmod +x /app/run.sh
Expand Down
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Makefile for cloning, building TDLib, building OpenSSL, and building a Go application (webBridgeBot) that uses TDLib

# Define variables
TDLIB_DIR=$(CURDIR)/tdlib
DOCKER_IMAGE_NAME=webbridgebot
DOCKER_TAG=latest
DOCKER_USERNAME=mshafiee
Expand Down
116 changes: 77 additions & 39 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
# WebBridgeBot

WebBridgeBot is a Telegram bot designed to bridge the gap between Telegram media content and web browsers. By forwarding video, audio and photo files to WebBridgeBot, users can generate a web URL that hosts a webpage. This webpage, in turn, communicates with WebBridgeBot via WebSocket, allowing for instant playback of the media in a web browser. This seamless integration makes it easier than ever to enjoy Telegram media on various devices such as TVs, game consoles, and web kiosks.
**WebBridgeBot** is a Telegram bot designed to bridge the gap between Telegram media content and web browsers. By forwarding video, audio, and photo files to WebBridgeBot, users can generate a web URL that hosts a webpage. This webpage communicates with WebBridgeBot via WebSocket, allowing for instant playback of the media in a web browser. This seamless integration makes it easier than ever to enjoy Telegram media on various devices such as TVs, game consoles, and web kiosks.

## Features

- Real-time WebSocket communication.
- Download and stream audio and video files from Telegram chats directly.
- Access and play media files through a user-friendly web interface.
- Easy command access within Telegram to navigate to the web interface.
- Efficient file downloads and streaming, with partial content delivery support.
- **Real-time WebSocket Communication:** Instantaneous interaction between the Telegram bot and the web interface, ensuring real-time playback of media files.
- **Stream Media Directly from Telegram:** Download and stream audio and video files from Telegram chats directly to a web interface.
- **User-friendly Web Interface:** Access and play media files through a simple and intuitive web interface, compatible with most modern devices.
- **Easy Navigation from Telegram:** Effortlessly navigate to the web interface using commands within Telegram.
- **Efficient Streaming with Partial Content Delivery:** Supports efficient file streaming with partial content delivery, allowing for responsive playback.

## Prerequisites

Before starting, ensure you have the following prerequisites installed:
Before you start, ensure you have the following prerequisites installed on your system:

- Docker
- Go (version 1.21 or newer as specified in the Dockerfile)
- Git
- CMake
- g++ (GNU C++ Compiler)
- Make
- zlib1g-dev (compression library)
- libssl-dev (SSL/TLS cryptography library)
- gperf (performance analyzer)
- **Docker:** Required for containerized deployment.
- **Go (version 1.21 or newer):** Necessary for building the application as specified in the Dockerfile.
- **Telegram API Credentials:** You need to obtain the `API ID` and `API Hash` from Telegram's [developer portal](https://my.telegram.org/).
- **Telegram Bot Token:** You can create a new bot and obtain a bot token using [BotFather](https://t.me/BotFather) on Telegram.

Additionally, you'll need:
## Admin Roles and User Authentication

- Telegram API credentials (API ID and API Hash)
- A Telegram Bot Token
### Admin Roles

When the bot is first initialized, the first user who interacts with it (typically using the `/start` command) is automatically granted admin rights. Admins have the following privileges:

- **Authorize Users:** Admins can authorize new users, allowing them to interact with the bot. This is done using the `/authorize <user_id>` command.
- **Grant Admin Privileges:** Admins can promote other users to admin status by adding the `admin` flag when authorizing a user (`/authorize <user_id> admin`).
- **Receive Notifications:** Admins are notified whenever a new user interacts with the bot. This allows them to decide whether to authorize the user or not.

### User Authentication

WebBridgeBot includes a user authentication mechanism to ensure that only authorized users can interact with the bot and access its web interface:

- **Automatic Authorization for the First User:** The first user to start the bot is automatically authorized and granted admin privileges.
- **Manual Authorization:** All subsequent users must be manually authorized by an admin. This is to prevent unauthorized access to the bot's features.
- **Unauthorized Users:** If a user who is not authorized attempts to interact with the bot, they will receive a message informing them that they need to be authorized by an admin. The bot will also notify the admins about this new user.
- **User Information Storage:** The bot stores user information in a database, which includes whether a user is authorized and whether they have admin privileges.

### Commands Overview

- **/start:** Initializes interaction with the bot. If the user is the first to start the bot, they are granted admin rights.
- **/authorize <user_id> [admin]:** Authorizes a user to interact with the bot. If `admin` is specified, the user is granted admin rights.
- **/deauthorize <user_id>:** Removes authorization from a user, preventing them from interacting with the bot.

Admins can use these commands to control who can use the bot and manage user roles effectively.

## Setup Instructions

Expand All @@ -40,27 +57,15 @@ git clone https://github.com/mshafiee/webbridgebot.git
cd webBridgeBot
```

### Building TDLib and OpenSSL

WebBridgeBot utilizes TDLib (Telegram Database Library) to interact with the Telegram API. The provided Makefile automates the process of cloning, building, and installing TDLib and OpenSSL, ensuring secure connections.

To prepare your environment, execute:

```bash
make all
```

This command will set up both TDLib and OpenSSL, placing the necessary files in `tdlib_install` and `openssl_install` directories, respectively.

### Building WebBridgeBot

After the dependencies are set up, build the WebBridgeBot application:
Once you have all dependencies in place, build the WebBridgeBot application:

```bash
make webBridgeBot
```

This compiles the `webBridgeBot` Go application.
This command compiles the `webBridgeBot` Go application, creating an executable that can be run on your system.

### Running WebBridgeBot with Docker

Expand All @@ -76,15 +81,15 @@ docker run -p 8080:8080 \
webbridgebot:latest
```

Ensure to replace `your_api_id`, `your_api_hash`, and `your_bot_token` with your actual Telegram credentials. Adjust `http://example.com` to your WebBridgeBot instance's URL.
Replace `your_api_id`, `your_api_hash`, and `your_bot_token` with your actual Telegram credentials. Also, adjust `http://example.com` to match the URL where your WebBridgeBot instance will be accessible.

### Running WebBridgeBot with Docker Compose

For a simpler and more streamlined deployment, you can use Docker Compose to manage the WebBridgeBot service. This approach automatically sets up the environment variables and port mappings based on your `.env` file and `docker-compose.yml` configuration.
For a simpler and more streamlined deployment, use Docker Compose to manage the WebBridgeBot service. This approach allows for easier management of environment variables and port mappings.

#### 1. Create a .env File

First, create a `.env` file in the root directory of the project with your Telegram credentials and other configurations as shown below:
First, create a `.env` file in the root directory of the project with your Telegram credentials and other necessary configurations:

```plaintext
# .env file content
Expand All @@ -93,19 +98,20 @@ API_HASH=abcdef1234567890abcdef1234567890
BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
BASE_URL=http://localhost:8080
PORT=8080
CACHE_DIRECTORY=.cache
```

Make sure to replace the placeholders with your actual data.

#### 2. Running with Docker Compose

To start the WebBridgeBot service using Docker Compose, navigate to the project's root directory and run:
To start the WebBridgeBot service using Docker Compose, navigate to the project's root directory and execute:

```bash
docker-compose up -d
```

This command builds (if necessary) and starts the container in the background. To view the logs of your service, you can use:
This command builds the Docker image (if not already built) and starts the container in the background. To view the logs of your service, use:

```bash
docker-compose logs -f
Expand All @@ -117,10 +123,42 @@ To stop and remove the containers, use:
docker-compose down
```

## Environment Variables

The WebBridgeBot uses several environment variables that must be configured properly:

- **API_ID:** Your Telegram API ID.
- **API_HASH:** Your Telegram API Hash.
- **BOT_TOKEN:** The token for your Telegram bot.
- **BASE_URL:** The base URL where the bot's web interface will be hosted.
- **PORT:** The port on which the web server will run.
- **CACHE_DIRECTORY:** The directory where cached files will be stored.

## Contributing

We welcome contributions to the WebBridgeBot project! Check out the issues tab for ways you can help make WebBridgeBot even better.
We welcome contributions to the WebBridgeBot project! To contribute:

1. Fork the repository.
2. Create a new branch with your feature or bugfix.
3. Submit a pull request with a clear description of your changes.

Check the issues tab for ways you can help make WebBridgeBot even better.

## License

WebBridgeBot is licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for more details.

## Troubleshooting

If you encounter issues during setup or while running the bot, consider the following steps:

- **Ensure all environment variables are correctly set.**
- **Check Docker and Docker Compose versions:** Make sure you are using compatible versions.
- **Review logs:** Use `docker-compose logs -f` to review the output logs for any errors or warnings.
- **Update Dependencies:** Regularly update dependencies to their latest versions to avoid compatibility issues.

For further assistance, please open an issue on the GitHub repository.

## Contact

For any questions or feedback, you can reach out to the maintainers through GitHub or Telegram.
58 changes: 48 additions & 10 deletions internal/bot/telegram_bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"io"
"log"
"net/http"
"os"
"strconv"
"strings"
"webBridgeBot/internal/data"
Expand Down Expand Up @@ -57,22 +56,21 @@ var (
)

// NewTelegramBot creates a new instance of TelegramBot.
func NewTelegramBot(config *config.Configuration) (*TelegramBot, error) {
func NewTelegramBot(config *config.Configuration, logger *log.Logger) (*TelegramBot, error) {
dsn := fmt.Sprintf("file:%s?mode=rwc", config.DatabasePath)
tgClient, err := gotgproto.NewClient(
config.ApiID,
config.ApiHash,
gotgproto.ClientTypeBot(config.BotToken),
&gotgproto.ClientOpts{
InMemory: true,
Session: sessionMaker.SqlSession(sqlite.Open(dsn)),
InMemory: true,
Session: sessionMaker.SqlSession(sqlite.Open(dsn)),
DisableCopyright: true,
})
if err != nil {
return nil, fmt.Errorf("failed to initialize Telegram client: %w", err)
}

logger := log.New(os.Stdout, "TelegramBot: ", log.Ldate|log.Ltime|log.Lshortfile)

// Initialize the database connection
db, err := sql.Open("sqlite", dsn)
if err != nil {
Expand Down Expand Up @@ -114,10 +112,14 @@ func (b *TelegramBot) registerHandlers() {
clientDispatcher := b.tgClient.Dispatcher
clientDispatcher.AddHandler(handlers.NewCommand("start", b.handleStartCommand))
clientDispatcher.AddHandler(handlers.NewCommand("authorize", b.handleAuthorizeUser))
clientDispatcher.AddHandler(handlers.NewCommand("deauthorize", b.handleDeauthorizeUser)) // Add this line
clientDispatcher.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("cb_"), b.handleCallbackQuery))
clientDispatcher.AddHandler(handlers.NewAnyUpdate(b.handleAnyUpdate))
clientDispatcher.AddHandler(handlers.NewMessage(filters.Message.Video, b.handleVideoMessages))
clientDispatcher.AddHandler(handlers.NewMessage(filters.Message.Audio, b.handleMediaMessages))
clientDispatcher.AddHandler(handlers.NewMessage(filters.Message.Video, b.handleMediaMessages))
clientDispatcher.AddHandler(handlers.NewMessage(filters.Message.Photo, b.handleMediaMessages))
}

func (b *TelegramBot) handleStartCommand(ctx *ext.Context, u *ext.Update) error {
chatID := u.EffectiveChat().GetID()
user := u.EffectiveUser()
Expand Down Expand Up @@ -246,13 +248,46 @@ func (b *TelegramBot) handleAuthorizeUser(ctx *ext.Context, u *ext.Update) error
return b.sendReply(ctx, u, fmt.Sprintf("User %d has been authorized%s.", targetUserID, adminMsg))
}

func (b *TelegramBot) handleDeauthorizeUser(ctx *ext.Context, u *ext.Update) error {
// Only allow admins to run this command
adminID := u.EffectiveUser().ID
userInfo, err := b.userRepository.GetUserInfo(adminID)
if err != nil {
b.logger.Printf("Failed to retrieve user info for admin check: %v", err)
return b.sendReply(ctx, u, "Failed to deauthorize the user.")
}

if !userInfo.IsAdmin {
return b.sendReply(ctx, u, "You are not authorized to perform this action.")
}

// Parse the user ID from the command
args := strings.Fields(u.EffectiveMessage.Text)
if len(args) < 2 {
return b.sendReply(ctx, u, "Usage: /deauthorize <user_id>")
}
targetUserID, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return b.sendReply(ctx, u, "Invalid user ID.")
}

// Deauthorize the user
err = b.userRepository.DeauthorizeUser(targetUserID)
if err != nil {
b.logger.Printf("Failed to deauthorize user %d: %v", targetUserID, err)
return b.sendReply(ctx, u, "Failed to deauthorize the user.")
}

return b.sendReply(ctx, u, fmt.Sprintf("User %d has been deauthorized.", targetUserID))
}

func (b *TelegramBot) handleAnyUpdate(ctx *ext.Context, u *ext.Update) error {
return nil
}

func (b *TelegramBot) handleVideoMessages(ctx *ext.Context, u *ext.Update) error {
func (b *TelegramBot) handleMediaMessages(ctx *ext.Context, u *ext.Update) error {
chatID := u.EffectiveChat().GetID()
b.logger.Printf("Processing video message for chat ID: %d", chatID)
b.logger.Printf("Processing media message for chat ID: %d", chatID)

if !b.isUserChat(ctx, chatID) {
return dispatcher.EndGroups
Expand Down Expand Up @@ -418,6 +453,9 @@ func isSupportedMedia(m *gtypes.Message) (bool, error) {
switch m.Media.(type) {
case *tg.MessageMediaDocument:
return true, nil
case *tg.MessageMediaPhoto:
// TODO: add photo support
return false, nil
default:
return false, nil
}
Expand Down Expand Up @@ -543,7 +581,7 @@ func (b *TelegramBot) handleStream(w http.ResponseWriter, r *http.Request) {
}

// Create a TelegramReader to stream the content.
lr, err := reader.NewTelegramReader(ctx, b.tgClient, file.Location, start, end, contentLength, b.config.BinaryCache)
lr, err := reader.NewTelegramReader(ctx, b.tgClient, file.Location, start, end, contentLength, b.config.BinaryCache, b.logger)
if err != nil {
b.logger.Printf("Error creating Telegram reader for message ID %d: %v", messageID, err)
http.Error(w, "Failed to initialize file stream", http.StatusInternalServerError)
Expand Down
Loading

0 comments on commit c7faf46

Please sign in to comment.