Telethon/telethon/_sessions/string.py

89 lines
2.6 KiB
Python
Raw Normal View History

2018-08-05 17:24:34 +03:00
import base64
import ipaddress
import struct
2019-05-06 09:55:24 +03:00
from .abstract import Session
2018-08-05 17:24:34 +03:00
from .memory import MemorySession
2021-09-19 14:45:19 +03:00
from .types import DataCenter, ChannelState, SessionState, Entity
2018-08-05 17:24:34 +03:00
_STRUCT_PREFORMAT = '>B{}sH256s'
2018-08-05 17:24:34 +03:00
CURRENT_VERSION = '1'
class StringSession(MemorySession):
"""
This session file can be easily saved and loaded as a string. According
to the initial design, it contains only the data that is necessary for
successful connection and authentication, so takeout ID is not stored.
2018-08-05 17:24:34 +03:00
It is thought to be used where you don't want to create any on-disk
files but would still like to be able to save and load existing sessions
by other means.
You can use custom `encode` and `decode` functions, if present:
* `encode` definition must be ``def encode(value: bytes) -> str:``.
* `decode` definition must be ``def decode(value: str) -> bytes:``.
2018-08-05 17:24:34 +03:00
"""
2019-05-03 14:59:17 +03:00
def __init__(self, string: str = None):
2018-08-05 17:24:34 +03:00
super().__init__()
2018-08-05 20:45:56 +03:00
if string:
if string[0] != CURRENT_VERSION:
raise ValueError('Not a valid string')
string = string[1:]
ip_len = 4 if len(string) == 352 else 16
2021-09-19 14:45:19 +03:00
dc_id, ip, port, key = struct.unpack(
2019-05-06 09:55:24 +03:00
_STRUCT_PREFORMAT.format(ip_len), StringSession.decode(string))
2018-08-05 20:45:56 +03:00
2021-09-19 14:45:19 +03:00
self.state = SessionState(
dc_id=dc_id,
user_id=0,
bot=False,
pts=0,
qts=0,
date=0,
seq=0,
takeout_id=0
)
if ip_len == 4:
ipv4 = int.from_bytes(ip, 'big', False)
ipv6 = None
else:
ipv4 = None
ipv6 = int.from_bytes(ip, 'big', signed=False)
self.dcs[dc_id] = DataCenter(
id=dc_id,
ipv4=ipv4,
ipv6=ipv6,
port=port,
auth=key
)
2018-08-05 17:24:34 +03:00
2019-05-03 14:59:17 +03:00
@staticmethod
def encode(x: bytes) -> str:
return base64.urlsafe_b64encode(x).decode('ascii')
@staticmethod
def decode(x: str) -> bytes:
return base64.urlsafe_b64decode(x)
2019-05-06 09:55:24 +03:00
def save(self: Session):
2021-09-19 14:45:19 +03:00
if not self.state:
2018-08-05 17:24:34 +03:00
return ''
2021-09-19 14:45:19 +03:00
if self.state.ipv6 is not None:
ip = self.state.ipv6.to_bytes(16, 'big', signed=False)
else:
ip = self.state.ipv6.to_bytes(4, 'big', signed=False)
2019-05-06 09:55:24 +03:00
return CURRENT_VERSION + StringSession.encode(struct.pack(
_STRUCT_PREFORMAT.format(len(ip)),
2021-09-19 14:45:19 +03:00
self.state.dc_id,
2018-08-05 17:24:34 +03:00
ip,
2021-09-19 14:45:19 +03:00
self.state.port,
self.dcs[self.state.dc_id].auth
))