Skip to content

Commit

Permalink
Merge pull request #190 from aahnik/fix-chat-ids
Browse files Browse the repository at this point in the history
Fix chat ids. Support username/phn no/links. Users no longer need to use chat ids anywhere!
  • Loading branch information
aahnik authored Jun 3, 2021
2 parents 4dcce1a + efba04a commit 96e08ec
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 45 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "tgcf"
version = "0.2.3"
version = "0.2.4"
description = "The ultimate tool to automate custom telegram message forwarding."
authors = ["aahnik <[email protected]>"]
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions tgcf/bot/live_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async def forward_command_handler(event):
except:
pass
config.CONFIG.forwards.append(forward)
config.from_to = config.load_from_to(config.CONFIG.forwards)
config.from_to = config.load_from_to(event.client, config.CONFIG.forwards)

await event.respond("Success")
config.write_config(config.CONFIG)
Expand Down Expand Up @@ -73,7 +73,7 @@ async def remove_command_handler(event):
print(source_to_remove)
config.CONFIG.forwards = remove_source(source_to_remove, config.CONFIG.forwards)
print(config.CONFIG.forwards)
config.from_to = config.load_from_to(config.CONFIG.forwards)
config.from_to = config.load_from_to(event.client, config.CONFIG.forwards)

await event.respond("Success")
config.write_config(config.CONFIG)
Expand Down
2 changes: 1 addition & 1 deletion tgcf/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def main(
else:
from tgcf.live import start_sync # pylint: disable=import-outside-toplevel

start_sync()
asyncio.run(start_sync())


# AAHNIK 2021
34 changes: 29 additions & 5 deletions tgcf/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import yaml
from dotenv import load_dotenv
from pydantic import BaseModel, validator # pylint: disable=no-name-in-module
from telethon import TelegramClient
from telethon.sessions import StringSession

from tgcf.const import CONFIG_ENV_VAR_NAME, CONFIG_FILE_NAME
Expand All @@ -20,7 +21,7 @@ class Forward(BaseModel):

# pylint: disable=too-few-public-methods
source: Union[int, str]
dest: List[Union[int, str]]
dest: List[Union[int, str]] = []
offset: int = 0
end: Optional[int] = None

Expand Down Expand Up @@ -148,14 +149,37 @@ def get_env_var(name: str, optional: bool = False) -> str:
CONFIG = read_config()


def load_from_to(forwards: List[Forward]) -> Dict:
"""Load a from -> to mapping."""
async def load_from_to(
client: TelegramClient, forwards: List[Forward]
) -> Dict[int, List[int]]:
"""Convert a list of Forward objects to a mapping.
Args:
client: Instance of Telegram client (logged in)
forwards: List of Forward objects
Returns:
Dict: key = chat id of source
value = List of chat ids of destinations
Notes:
-> The Forward objects may contain username/phn no/links
-> But this mapping strictly contains signed integer chat ids
-> Chat ids are essential for how storage is implemented
-> Storage is essential for edit, delete and reply syncs
"""
from_to_dict = {}

async def _(peer):
return await client.get_peer_id(peer)

for forward in forwards:
from_to_dict[forward.source] = forward.dest
src = await _(forward.source)
from_to_dict[src] = [await _(dest) for dest in forward.dest]
logging.info(f"From to dict is {from_to_dict}")
return from_to_dict


from_to = load_from_to(CONFIG.forwards)
from_to = {}

logging.info("config.py got executed")
54 changes: 25 additions & 29 deletions tgcf/live.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from typing import Union

from telethon import events
from telethon import TelegramClient, events, functions, types
from telethon.tl.custom.message import Message

from tgcf import config, const
Expand Down Expand Up @@ -32,25 +32,23 @@ async def new_message_handler(event: Union[Message, events.NewMessage]) -> None:
del st.stored[key]
break

to_send_to = config.from_to.get(chat_id)
dest = config.from_to.get(chat_id)

if to_send_to:

tm = await apply_plugins(message)
if not tm:
return
tm = await apply_plugins(message)
if not tm:
return

if event.is_reply:
r_event = st.DummyEvent(chat_id, event.reply_to_msg_id)
r_event_uid = st.EventUid(r_event)
if event.is_reply:
r_event = st.DummyEvent(chat_id, event.reply_to_msg_id)
r_event_uid = st.EventUid(r_event)

st.stored[event_uid] = {}
for recipient in to_send_to:
if event.is_reply and r_event_uid in st.stored:
tm.reply_to = st.stored.get(r_event_uid).get(recipient)
fwded_msg = await send_message(recipient, tm)
st.stored[event_uid].update({recipient: fwded_msg})
tm.clear()
st.stored[event_uid] = {}
for d in dest:
if event.is_reply and r_event_uid in st.stored:
tm.reply_to = st.stored.get(r_event_uid).get(d)
fwded_msg = await send_message(d, tm)
st.stored[event_uid].update({d: fwded_msg})
tm.clear()


async def edited_message_handler(event) -> None:
Expand Down Expand Up @@ -82,10 +80,10 @@ async def edited_message_handler(event) -> None:
await msg.edit(tm.text)
return

to_send_to = config.from_to.get(event.chat_id)
dest = config.from_to.get(chat_id)

for recipient in to_send_to:
await send_message(recipient, tm)
for d in dest:
await send_message(d, tm)
tm.clear()


Expand All @@ -100,7 +98,7 @@ async def deleted_message_handler(event):
event_uid = st.EventUid(event)
fwded_msgs = st.stored.get(event_uid)
if fwded_msgs:
for msg in fwded_msgs:
for _, msg in fwded_msgs.items():
await msg.delete()
return

Expand All @@ -122,14 +120,12 @@ async def deleted_message_handler(event):
pass


def start_sync() -> None:
async def start_sync() -> None:
"""Start tgcf live sync."""
# pylint: disable=import-outside-toplevel
from telethon.sync import TelegramClient, functions, types

client = TelegramClient(config.SESSION, config.API_ID, config.API_HASH)
client.start(bot_token=config.BOT_TOKEN)
is_bot = client.is_bot()
await client.start(bot_token=config.BOT_TOKEN)
is_bot = await client.is_bot()

for key, val in ALL_EVENTS.items():
if key.startswith("bot"):
Expand All @@ -141,13 +137,13 @@ def start_sync() -> None:
logging.info(f"Added event handler for {key}")

if is_bot and const.REGISTER_COMMANDS:
client(
await client(
functions.bots.SetBotCommandsRequest(
commands=[
types.BotCommand(command=key, description=value)
for key, value in const.COMMANDS.items()
]
)
)

client.run_until_disconnected()
config.from_to = await config.load_from_to(client, config.CONFIG.forwards)
await client.run_until_disconnected()
18 changes: 11 additions & 7 deletions tgcf/past.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from telethon.tl.custom.message import Message
from telethon.tl.patched import MessageService

from tgcf import config
from tgcf import storage as st
from tgcf.config import API_HASH, API_ID, CONFIG, SESSION, write_config
from tgcf.plugins import apply_plugins
Expand All @@ -22,12 +23,15 @@
async def forward_job() -> None:
"""Forward all existing messages in the concerned chats."""
async with TelegramClient(SESSION, API_ID, API_HASH) as client:
config.from_to = await config.load_from_to(client, config.CONFIG.forwards)
client: TelegramClient
for forward in CONFIG.forwards:
for from_to, forward in zip(config.from_to.items(), config.CONFIG.forwards):
src, dest = from_to
last_id = 0
logging.info(f"Forwarding messages from {forward.source} to {forward.dest}")
forward: config.Forward
logging.info(f"Forwarding messages from {src} to {dest}")
async for message in client.iter_messages(
forward.source, reverse=True, offset_id=forward.offset
src, reverse=True, offset_id=forward.offset
):
message: Message
event = st.DummyEvent(message.chat_id, message.id)
Expand All @@ -48,11 +52,11 @@ async def forward_job() -> None:
message.chat_id, message.reply_to_msg_id
)
r_event_uid = st.EventUid(r_event)
for destination in forward.dest:
for d in dest:
if message.is_reply and r_event_uid in st.stored:
tm.reply_to = st.stored.get(r_event_uid).get(destination)
fwded_msg = await send_message(destination, tm)
st.stored[event_uid].update({fwded_msg.chat_id: fwded_msg.id})
tm.reply_to = st.stored.get(r_event_uid).get(d)
fwded_msg = await send_message(d, tm)
st.stored[event_uid].update({d: fwded_msg.id})
tm.clear()
last_id = message.id
logging.info(f"forwarding message with id = {last_id}")
Expand Down

0 comments on commit 96e08ec

Please sign in to comment.