├── .gitignore ├── README.md ├── config.yml-sample ├── forwardgram.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | venv 3 | .vscode 4 | __pycache__ 5 | *.exe 6 | config.yml 7 | *.session 8 | *.session-journal -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # forwardgram 2 | Forward messages from multiple Telegram channels or chats to one (or more) chat or channel of your own! 3 | 4 | ## Prerequisites 5 | - Python 3.6+ 6 | 7 | ## Setup 8 | - `python3 -m pip install -r requirements.txt`. 9 | - Fill out a configuration file. An example file can be found at `config.yml-sample`. 10 | 11 | ## Run 12 | `python3 forwardgram.py {YOUR_CONFIG_FILE}` 13 | Please note that in the first time initializing the script, you will be requried to validate your phone number using telegram API. This happens only at the first time (per session name). 14 | -------------------------------------------------------------------------------- /config.yml-sample: -------------------------------------------------------------------------------- 1 | api_id: 123456 # This has to be an integer. Read more [here](https://core.telegram.org/api/obtaining_api_id) 2 | api_hash: 'abcdefg' # Long 32 characters hash identifier. Read more [here](https://core.telegram.org/api/obtaining_api_id) 3 | session_name: 'forwardgram' # Session name. Only one session (with a unique session name) can run at a time 4 | 5 | # The channel names that you'd like to forward messages from. 6 | # The user running the client must have these channels present on it's dialogs. 7 | input_channel_names: 8 | - 'Input Channel Name 1' 9 | - 'Input Channel Name 2' 10 | 11 | # The output channel names that the messages will be forwarded to. 12 | # The user running the client must have a write access to those channels, and have the channels present on theirs dialogs. 13 | output_channel_names: 14 | - 'Output Channel Name 1' 15 | - 'Output Channel Name 2' 16 | 17 | # The channel IDs that you'd like to forward messages from. (You can get a channel ID by forwarding any message from it to @userinfobot , and removing the -100 from the start ) 18 | input_channel_ids: 19 | - ID1 # Input Channel ID without quotes '' 20 | - ID2 21 | 22 | # The output channel IDs that the messages will be forwarded to. (You can get a channel ID by forwarding any message from it to @userinfobot , and removing the -100 from the start ) 23 | output_channel_ids: 24 | - ID1 # Output Channel ID without quotes '' 25 | - ID2 26 | 27 | # An empty list should be set like this: 28 | # input_channel_ids: [] -------------------------------------------------------------------------------- /forwardgram.py: -------------------------------------------------------------------------------- 1 | from telethon import TelegramClient, events, sync 2 | from telethon.tl.types import InputChannel 3 | import yaml 4 | import sys 5 | import logging 6 | 7 | logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') 8 | logging.getLogger('telethon').setLevel(level=logging.WARNING) 9 | logger = logging.getLogger(__name__) 10 | 11 | 12 | def start(config): 13 | client = TelegramClient(config["session_name"], 14 | config["api_id"], 15 | config["api_hash"]) 16 | client.start() 17 | 18 | input_channels_entities = [] 19 | output_channel_entities = [] 20 | for d in client.iter_dialogs(): 21 | if d.name in config["input_channel_names"] or d.entity.id in config["input_channel_ids"]: 22 | input_channels_entities.append(InputChannel(d.entity.id, d.entity.access_hash)) 23 | if d.name in config["output_channel_names"] or d.entity.id in config["output_channel_ids"]: 24 | output_channel_entities.append(InputChannel(d.entity.id, d.entity.access_hash)) 25 | 26 | if not output_channel_entities: 27 | logger.error(f"Could not find any output channels in the user's dialogs") 28 | sys.exit(1) 29 | 30 | if not input_channels_entities: 31 | logger.error(f"Could not find any input channels in the user's dialogs") 32 | sys.exit(1) 33 | 34 | logging.info(f"Listening on {len(input_channels_entities)} channels. Forwarding messages to {len(output_channel_entities)} channels.") 35 | 36 | @client.on(events.NewMessage(chats=input_channels_entities)) 37 | async def handler(event): 38 | for output_channel in output_channel_entities: 39 | await client.forward_messages(output_channel, event.message) 40 | 41 | client.run_until_disconnected() 42 | 43 | if __name__ == "__main__": 44 | if len(sys.argv) < 2: 45 | print(f"Usage: {sys.argv[0]} {{CONFIG_PATH}}") 46 | sys.exit(1) 47 | with open(sys.argv[1], 'rb') as f: 48 | config = yaml.safe_load(f) 49 | start(config) 50 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | telethon 2 | pyyaml --------------------------------------------------------------------------------