repos
/
irgramd
/ annotate_shade
exclam: Add upload (!upl) command to upload files/media to chats/channels
Annotate for file /irgramd
2019-07-17 Peter
1
#!/usr/bin/env python3
2022-02-20 E.
2
#
01:25:27 '
3
# irgramd: IRC-Telegram gateway - Main file
'
4
#
'
5
# Copyright (c) 2019 Peter Bui <pbui@bx612.space>
2024-04-14 E.
6
# Copyright (c) 2020-2024 E. Bosch <presidev@AT@gmail.com>
2022-02-20 E.
7
#
01:25:27 '
8
# Use of this source code is governed by a MIT style license that
'
9
# can be found in the LICENSE file included in this project.
2019-07-17 Peter
10
01:23:35 '
11
import logging
'
12
import os
2021-01-27 E.
13
import asyncio
23:13:48 '
14
2019-07-17 Peter
15
import tornado.options
01:23:35 '
16
import tornado.tcpserver
2021-12-08 E.
17
import ssl
2019-07-17 Peter
18
2020-11-19 E.
19
# Local modules
19:41:24 '
20
2020-11-22 E.
21
from irc import IRCHandler
22:57:38 '
22
from telegram import TelegramHandler
2023-12-20 E.
23
from utils import parse_loglevel
2019-07-17 Peter
24
2019-07-26 Peter
25
# IRC Telegram Daemon
01:05:21 '
26
'
27
class IRCTelegramd(tornado.tcpserver.TCPServer):
2021-12-12 E.
28
def __init__(self, logger, settings):
2021-12-11 E.
29
self.logger = logger
2022-03-03 E.
30
effective_port = settings['irc_port']
2021-12-08 E.
31
00:39:32 '
32
if settings['tls']:
'
33
if not settings['tls_cert']: # error
'
34
self.logger.error('TLS configured but certificate not present')
'
35
exit(1)
'
36
tls_context = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
2021-12-10 E.
37
tls_context.load_cert_chain(os.path.expanduser(settings['tls_cert']), os.path.expanduser(settings['tls_key']))
2021-12-08 E.
38
if not effective_port:
00:39:32 '
39
effective_port = 6697
'
40
self.logger.info('TLS configured')
'
41
else:
'
42
tls_context = None
'
43
if not effective_port:
'
44
effective_port = 6667
'
45
'
46
tornado.tcpserver.TCPServer.__init__(self, ssl_options=tls_context)
'
47
2022-03-03 E.
48
self.address = settings['irc_address']
2021-12-08 E.
49
self.port = effective_port
2020-11-22 E.
50
self.irc_handler = None
22:57:38 '
51
self.tg_handler = None
2019-07-26 Peter
52
2019-07-17 Peter
53
01:23:35 '
54
async def handle_stream(self, stream, address):
2020-11-22 E.
55
await self.irc_handler.run(stream, address)
2019-07-17 Peter
56
2021-12-12 E.
57
async def run(self, settings):
2019-07-17 Peter
58
self.listen(self.port, self.address)
2020-11-19 E.
59
self.logger.info('irgramd listening on %s:%s', self.address, self.port)
2021-12-12 E.
60
self.irc_handler = IRCHandler(settings)
01:15:52 '
61
self.tg_handler = TelegramHandler(self.irc_handler, settings)
2020-11-22 E.
62
self.irc_handler.set_telegram(self.tg_handler)
2021-01-27 E.
63
await self.tg_handler.initialize_telegram()
2019-07-17 Peter
64
01:23:35 '
65
'
66
# Main Execution
'
67
'
68
if __name__ == '__main__':
2023-12-20 E.
69
# Remove tornado.log options (ugly hacks but these must not be defined)
00:50:56 '
70
tornado.options.options.logging = None
'
71
tornado_log_options = tuple(x for x in tornado.options.options._options.keys() if x != 'help' and x != 'logging')
'
72
for opt in tornado_log_options:
'
73
del tornado.options.options._options[opt]
'
74
# and reuse "--logging" to document empty "--" ;)
'
75
tornado.options.options._options['logging'].help = 'Stop parsing options'
'
76
for att in ('name', 'metavar', 'group_name', 'default'):
'
77
setattr(tornado.options.options._options['logging'], att, '')
'
78
# Define irgramd options
2022-02-16 E.
79
tornado.options.define('api_hash', default=None, metavar='HASH', help='Telegram API Hash for your account (obtained from https://my.telegram.org/apps)')
01:18:10 '
80
tornado.options.define('api_id', type=int, default=None, metavar='ID', help='Telegram API ID for your account (obtained from https://my.telegram.org/apps)')
2022-03-08 E.
81
tornado.options.define('ask_code', default=False, help='Ask authentication code (sent by Telegram) in console instead of "code" service command in IRC')
2024-04-14 E.
82
tornado.options.define('cache_dir', default='~/.cache/irgramd', metavar='PATH', help='Cache directory where telegram media is saved by default')
2023-06-10 E.
83
tornado.options.define('char_in_encoding', default='utf-8', metavar='ENCODING', help='Character input encoding for IRC')
22:44:55 '
84
tornado.options.define('char_out_encoding', default='utf-8', metavar='ENCODING', help='Character output encoding for IRC')
2022-02-16 E.
85
tornado.options.define('config', default='irgramdrc', metavar='CONFIGFILE', help='Config file absolute or relative to `config_dir` (command line options override it)')
2021-12-11 E.
86
tornado.options.define('config_dir', default='~/.config/irgramd', metavar='PATH', help='Configuration directory where telegram session info is saved')
2023-10-15 E.
87
tornado.options.define('download_media', default=True, help='Enable download of any media (photos, documents, etc.), if not set only a message of media will be shown')
2023-10-15 E.
88
tornado.options.define('download_notice', default=10, metavar='SIZE (MiB)', help='Enable a notice when a download starts if its size is greater than SIZE, this is useful when a download takes some time to be completed')
2023-04-29 E.
89
tornado.options.define('emoji_ascii', default=False, help='Replace emoji with ASCII emoticons')
2023-07-20 E.
90
tornado.options.define('geo_url', type=str, default=None, metavar='TEMPLATE_URL', help='Use custom URL for showing geo latitude/longitude location, eg. OpenStreetMap')
2023-05-06 E.
91
tornado.options.define('hist_timestamp_format', metavar='DATETIME_FORMAT', help='Format string for timestamps in history, see https://www.strfti.me')
2022-03-03 E.
92
tornado.options.define('irc_address', default='127.0.0.1', metavar='ADDRESS', help='Address to listen on for IRC')
2022-02-16 E.
93
tornado.options.define('irc_nicks', type=str, multiple=True, metavar='nick,..', help='List of nicks allowed for IRC, if `pam` and optionally `pam_group` are set, PAM authentication will be used instead')
00:58:19 '
94
tornado.options.define('irc_password', default='', metavar='PASSWORD', help='Password for IRC authentication, if `pam` is set, PAM authentication will be used instead')
2022-03-03 E.
95
tornado.options.define('irc_port', type=int, default=None, metavar='PORT', help='Port to listen on for IRC. (default 6667, default with TLS 6697)')
2023-12-20 E.
96
tornado.options.define('log_file', default=None, metavar='PATH', help='File where logs are appended, if not set will be stderr')
00:50:56 '
97
tornado.options.define('log_level', default='INFO', metavar='DEBUG|INFO|WARNING|ERROR|CRITICAL|NONE', help='The log level (and any higher to it) that will be logged')
2024-04-14 E.
98
tornado.options.define('media_dir', default=None, metavar='PATH', help='Directory where Telegram media files are downloaded, default "media" in `cache_dir`')
2022-01-30 E.
99
tornado.options.define('media_url', default=None, metavar='BASE_URL', help='Base URL for media files, should be configured in the external (to irgramd) webserver')
2021-12-13 E.
100
tornado.options.define('pam', default=False, help='Use PAM for IRC authentication, if not set you should set `irc_password`')
20:31:17 '
101
tornado.options.define('pam_group', default=None, metavar='GROUP', help='Unix group allowed if `pam` enabled, if empty any user is allowed')
2022-02-16 E.
102
tornado.options.define('phone', default=None, metavar='PHONE_NUMBER', help='Phone number associated with the Telegram account to receive the authorization codes if necessary')
2023-04-26 E.
103
tornado.options.define('quote_length', default=50, metavar='LENGTH', help='Max length of the text quoted in replies and reactions, if longer is truncated')
2022-02-26 E.
104
tornado.options.define('service_user', default='TelegramServ', metavar='SERVICE_NICK', help='Nick of the service/control user, must be a nick not used by a real Telegram user')
2022-02-22 E.
105
tornado.options.define('test', default=False, help='Connect to Telegram test environment')
01:37:33 '
106
tornado.options.define('test_datacenter', default=2, metavar='DATACENTER_NUMBER', help='Datacenter to connect to Telegram test environment')
'
107
tornado.options.define('test_host', default=None, metavar='HOST_IP', help='Host to connect to Telegram test environment (default: use a internal table depending on datacenter)')
'
108
tornado.options.define('test_port', default=443, metavar='PORT', help='Port to connect to Telegram test environment')
2023-05-06 E.
109
tornado.options.define('timezone', default='UTC', metavar='TIMEZONE', help='Timezone to use for dates (timestamps in history, last in dialogs, etc.)')
2022-02-16 E.
110
tornado.options.define('tls', default=False, help='Use TLS/SSL encrypted connection for IRC server')
00:58:19 '
111
tornado.options.define('tls_cert', default=None, metavar='CERTFILE', help='IRC server certificate chain for TLS/SSL, also can contain private key if not defined with `tls_key`')
'
112
tornado.options.define('tls_key', default=None, metavar='KEYFILE', help='IRC server private key for TLS/SSL')
2024-04-14 E.
113
tornado.options.define('upload_dir', default=None, metavar='PATH', help='Directory where files to upload are picked up, default "upload" in `cache_dir`')
2023-12-20 E.
114
try:
00:50:56 '
115
# parse cmd line first time to get --config and --config_dir
'
116
tornado.options.parse_command_line()
'
117
except Exception as exc:
'
118
print(exc)
'
119
exit(1)
2021-12-11 E.
120
config_file = os.path.expanduser(tornado.options.options.config)
21:32:43 '
121
config_dir = os.path.expanduser(tornado.options.options.config_dir)
'
122
if not os.path.exists(config_dir):
'
123
os.makedirs(config_dir)
2023-12-20 E.
124
defered_logs = [(logging.INFO, 'Configuration Directory: %s', config_dir)]
2021-12-11 E.
125
21:32:43 '
126
if not os.path.isabs(config_file):
'
127
config_file = os.path.join(config_dir, config_file)
'
128
if os.path.isfile(config_file):
2023-12-20 E.
129
defered_logs.append((logging.INFO, 'Using configuration file: %s', config_file))
00:50:56 '
130
try:
'
131
tornado.options.parse_config_file(config_file)
'
132
except Exception as exc:
'
133
print(exc)
'
134
exit(1)
2021-12-11 E.
135
else:
2023-12-20 E.
136
defered_logs.append((logging.WARNING, 'Configuration file not present, using only command line options and defaults'))
2021-12-11 E.
137
# parse cmd line second time to override file options
21:32:43 '
138
tornado.options.parse_command_line()
2019-07-26 Peter
139
01:05:21 '
140
options = tornado.options.options.as_dict()
2021-12-12 E.
141
options['config_dir'] = config_dir
01:15:52 '
142
2023-12-20 E.
143
# configure logging
00:50:56 '
144
loglevel = parse_loglevel(options['log_level'])
'
145
if loglevel == False:
'
146
print("Option 'log_level' requires one of these values: {}".format(tornado.options.options._options['log-level'].metavar))
'
147
exit(1)
'
148
logger_formats = { 'datefmt':'%Y-%m-%d %H:%M:%S', 'format':'[%(levelname).1s %(asctime)s %(module)s:%(lineno)d] %(message)s' }
'
149
logger = logging.getLogger()
'
150
if options['log_file']:
'
151
logging.basicConfig(filename=options['log_file'], level=loglevel, **logger_formats)
'
152
else:
'
153
logging.basicConfig(level=loglevel, **logger_formats)
'
154
'
155
for log in defered_logs:
'
156
logger.log(*log)
'
157
'
158
# main loop
2021-12-12 E.
159
irc_server = IRCTelegramd(logger, options)
2023-03-19 E.
160
loop = asyncio.new_event_loop()
01:40:30 '
161
loop.run_until_complete(irc_server.run(options))
'
162
loop.run_forever()