Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Plugin] Sender #478

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions tgcf/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
import os
import sys
from typing import Dict, List, Optional, Union
from typing import Dict, List, Optional, Union, Any

from dotenv import load_dotenv
from pydantic import BaseModel, validator # pylint: disable=no-name-in-module
Expand Down Expand Up @@ -207,19 +207,6 @@ async def load_admins(client: TelegramClient):
return ADMINS


def get_SESSION():
if CONFIG.login.SESSION_STRING and CONFIG.login.user_type == 1:
logging.info("using session string")
SESSION = StringSession(CONFIG.login.SESSION_STRING)
elif CONFIG.login.BOT_TOKEN and CONFIG.login.user_type == 0:
logging.info("using bot account")
SESSION = "tgcf_bot"
else:
logging.warning("Login information not set!")
sys.exit()
return SESSION


def setup_mongo(client):

mydb = client[MONGO_DB_NAME]
Expand Down Expand Up @@ -257,3 +244,16 @@ def read_db():
from_to = {}
is_bot: Optional[bool] = None
logging.info("config.py got executed")


def get_SESSION(section: Any = CONFIG.login, default: str = 'tgcf_bot'):
if section.SESSION_STRING and section.user_type == 1:
logging.info("using session string")
SESSION = StringSession(section.SESSION_STRING)
elif section.BOT_TOKEN and section.user_type == 0:
logging.info("using bot account")
SESSION = default
else:
logging.warning("Login information not set!")
sys.exit()
return SESSION
5 changes: 4 additions & 1 deletion tgcf/live.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from tgcf import storage as st
from tgcf.bot import get_events
from tgcf.config import CONFIG, get_SESSION
from tgcf.plugins import apply_plugins
from tgcf.plugins import apply_plugins, load_async_plugins
from tgcf.utils import clean_session_files, send_message


Expand Down Expand Up @@ -119,6 +119,9 @@ async def start_sync() -> None:
# clear past session files
clean_session_files()

# load async plugins defined in plugin_models
await load_async_plugins()

SESSION = get_SESSION()
client = TelegramClient(
SESSION,
Expand Down
6 changes: 5 additions & 1 deletion tgcf/past.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
from tgcf import config
from tgcf import storage as st
from tgcf.config import CONFIG, get_SESSION, write_config
from tgcf.plugins import apply_plugins
from tgcf.plugins import apply_plugins, load_async_plugins
from tgcf.utils import clean_session_files, send_message


async def forward_job() -> None:
"""Forward all existing messages in the concerned chats."""
clean_session_files()

# load async plugins defined in plugin_models
await load_async_plugins()

if CONFIG.login.user_type != 1:
logging.warning(
"You cannot use bot account for tgcf past mode. Telegram does not allow bots to access chat history."
Expand Down
10 changes: 10 additions & 0 deletions tgcf/plugin_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ class Caption(BaseModel):
header: str = ""
footer: str = ""

class Sender(BaseModel):
check: bool = False
user_type: int = 0 # 0:bot, 1:user
BOT_TOKEN: str = ""
SESSION_STRING: str = ""

class PluginConfig(BaseModel):
filter: Filters = Filters()
Expand All @@ -89,3 +94,8 @@ class PluginConfig(BaseModel):
ocr: OcrConfig = OcrConfig()
replace: Replace = Replace()
caption: Caption = Caption()
sender: Sender = Sender()


# List of plugins that need to load asynchronously
ASYNC_PLUGIN_IDS = ['sender']
17 changes: 15 additions & 2 deletions tgcf/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from telethon.tl.custom.message import Message

from tgcf.config import CONFIG
from tgcf.plugin_models import FileType
from tgcf.plugin_models import FileType, ASYNC_PLUGIN_IDS
from tgcf.utils import cleanup, stamp

PLUGINS = CONFIG.plugins
Expand All @@ -29,6 +29,7 @@ def __init__(self, message: Message) -> None:
self.new_file = None
self.cleanup = False
self.reply_to = None
self.client = self.message.client

async def get_file(self) -> str:
"""Downloads the file in the message and returns the path where its saved."""
Expand Down Expand Up @@ -57,6 +58,9 @@ class TgcfPlugin:
def __init__(self, data: Dict[str, Any]) -> None: # TODO data type has changed
self.data = data

async def __ainit__(self) -> None:
"""Asynchronous initialization here."""

def modify(self, tm: TgcfMessage) -> TgcfMessage:
"""Modify the message here."""
return tm
Expand Down Expand Up @@ -93,13 +97,22 @@ def load_plugins() -> Dict[str, TgcfPlugin]:
logging.error(f"Plugin id for {plugin_id} does not match expected id.")
continue
except AttributeError:
logging.error(f"Found plugin {plugin_id}, but plguin class not found.")
logging.error(f"Found plugin {plugin_id}, but plugin class not found.")
else:
logging.info(f"Loaded plugin {plugin_id}")
_plugins.update({plugin.id_: plugin})
return _plugins


async def load_async_plugins() -> None:
"""Load async plugins specified plugin_models."""
if plugins:
for id in ASYNC_PLUGIN_IDS:
if id in plugins:
await plugins[id].__ainit__()
logging.info(f"Plugin {id} asynchronously loaded")


async def apply_plugins(message: Message) -> TgcfMessage:
"""Apply all loaded plugins to a message."""
tm = TgcfMessage(message)
Expand Down
31 changes: 31 additions & 0 deletions tgcf/plugins/sender.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import logging
import sys

from tgcf.plugins import TgcfMessage, TgcfPlugin
from tgcf.config import CONFIG, get_SESSION
from telethon import TelegramClient

class TgcfSender(TgcfPlugin):
id_ = "sender"

async def __ainit__(self) -> None:
sender = TelegramClient(
get_SESSION(CONFIG.plugins.sender, 'tgcf_sender'),
CONFIG.login.API_ID,
CONFIG.login.API_HASH,
)
if self.data.user_type == 0:
if self.data.BOT_TOKEN == "":
logging.warning("[Sender] Bot token not found, but login type is set to bot.")
sys.exit()
await sender.start(bot_token=self.data.BOT_TOKEN)
else:
await sender.start()
self.sender = sender

async def modify(self, tm: TgcfMessage) -> TgcfMessage:
tm.client = self.sender
if tm.file_type != "nofile":
tm.new_file = await tm.get_file()
tm.cleanup = True
return tm
2 changes: 1 addition & 1 deletion tgcf/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def platform_info():

async def send_message(recipient: EntityLike, tm: "TgcfMessage") -> Message:
"""Forward or send a copy, depending on config."""
client: TelegramClient = tm.message.client
client: TelegramClient = tm.client
if CONFIG.show_forwarded_from:
return await client.forward_messages(recipient, tm.message)
if tm.new_file:
Expand Down
43 changes: 43 additions & 0 deletions tgcf/web_ui/pages/4_🔌_Plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,48 @@
"You can have blank lines inside header and footer, to make space between the orignal message and captions."
)

with st.expander("Sender"):
st.write("Modify the sender of forwarded messages other than the current user/bot")
st.warning("Show 'Forwarded from' option must be disabled or else messages will not be sent",icon="⚠️")
CONFIG.plugins.sender.check = st.checkbox(
"Set sender to:", value=CONFIG.plugins.sender.check
)
leftpad,content,rightpad = st.columns([0.05,0.9,0.05])
with content:
user_type = st.radio("Account Type", ["Bot", "User"], index=CONFIG.plugins.sender.user_type,horizontal=True)
if user_type == "Bot":
CONFIG.plugins.sender.user_type = 0
CONFIG.plugins.sender.BOT_TOKEN = st.text_input(
"Bot Token", value=CONFIG.plugins.sender.BOT_TOKEN, type="password"
)
else:
CONFIG.plugins.sender.user_type = 1
CONFIG.plugins.sender.SESSION_STRING = st.text_input(
"Session String", CONFIG.plugins.sender.SESSION_STRING, type="password"
)
st.markdown(
"""
###### How to get session string?

Link to repl: https://replit.com/@aahnik/tg-login?v=1

<p style="line-height:0px;margin-bottom:2em">
<i>Click on the above link and enter api id, api hash, and phone no to generate session string.</i>
</p>


> <small>**Note from developer:**<small>
>
> <small>Due some issues logging in with a user account using a phone no is not supported in this web interface.</small>
>
> <small>I have built a command-line program named tg-login (https://github.com/aahnik/tg-login) that can generate the session string for you.</small>
>
> <small>You can run tg-login on your computer, or securely in this repl. tg-login is open source, and you can also inspect the bash script running in the repl.</small>
>
> <small>What is a session string?</small>
> <small>https://docs.telethon.dev/en/stable/concepts/sessions.html#string-sessions</small>
"""
,unsafe_allow_html=True)

if st.button("Save"):
write_config(CONFIG)