pyrogram-client 0.0.5__tar.gz → 0.0.7.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {pyrogram_client-0.0.5/pyrogram_client.egg-info → pyrogram_client-0.0.7.dev2}/PKG-INFO +1 -1
  2. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyro_client/client/base.py +38 -12
  3. pyrogram_client-0.0.7.dev2/pyro_client/client/bot.py +39 -0
  4. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyro_client/client/user.py +33 -38
  5. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyro_client/loader.py +8 -0
  6. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyro_client/storage.py +50 -42
  7. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2/pyrogram_client.egg-info}/PKG-INFO +1 -1
  8. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyrogram_client.egg-info/SOURCES.txt +0 -1
  9. pyrogram_client-0.0.5/pyro_client/client/bot.py +0 -11
  10. pyrogram_client-0.0.5/pyro_client/client/single.py +0 -40
  11. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/.env.sample +0 -0
  12. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/.gitignore +0 -0
  13. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/.pre-commit-config.yaml +0 -0
  14. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/makefile +0 -0
  15. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyproject.toml +0 -0
  16. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyro_client/client/dc.json +0 -0
  17. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyro_client/client/file.py +0 -0
  18. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyrogram_client.egg-info/dependency_links.txt +0 -0
  19. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyrogram_client.egg-info/requires.txt +0 -0
  20. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/pyrogram_client.egg-info/top_level.txt +0 -0
  21. {pyrogram_client-0.0.5 → pyrogram_client-0.0.7.dev2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrogram-client
3
- Version: 0.0.5
3
+ Version: 0.0.7.dev2
4
4
  Author-email: Mike Artemiev <mixartemev@gmail.com>
5
5
  Project-URL: Homepage, https://gitlab.com/XyncNet/pyro-client
6
6
  Project-URL: Repository, https://gitlab.com/XyncNet/pyro-client
@@ -4,30 +4,55 @@ from io import BytesIO
4
4
  from typing import Literal
5
5
 
6
6
  from pyrogram import Client
7
+ from pyrogram.errors import AuthKeyUnregistered, Unauthorized
7
8
  from pyrogram.filters import chat, contact, AndFilter
8
9
  from pyrogram.handlers import MessageHandler
9
10
  from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
11
+ from x_auth.models import Session, App, Username
10
12
 
11
- from pyro_client.client.single import SingleMeta
12
13
  from pyro_client.storage import PgStorage
13
14
 
14
15
  AuthTopic = Literal["phone", "code", "pass"]
15
16
 
16
17
 
17
- def sync_call_async(async_func, *args):
18
- loop = asyncio.get_event_loop() # Получаем текущий запущенный цикл
19
- if loop.is_running():
20
- future = asyncio.run_coroutine_threadsafe(async_func(*args), loop)
21
- return future.result(5) # Блокируемся, пока корутина не выполнится
18
+ class BaseClient(Client):
19
+ storage: PgStorage
20
+ uid: int = None
22
21
 
22
+ _insts: dict[int, "BaseClient"] = {}
23
23
 
24
- class BaseClient(Client, metaclass=SingleMeta):
25
- storage: PgStorage
24
+ def __new__(cls, uid: int, *args, **kwargs):
25
+ """Single client for each uid"""
26
+ cls.uid = uid
27
+ if uid not in cls._insts:
28
+ cls._insts[uid] = Client.__new__(cls)
29
+ return cls._insts[uid]
26
30
 
27
- def __init__(self, name: str, api_id, api_hash, *args, **kwargs):
28
- super().__init__(
29
- name, api_id=api_id, api_hash=api_hash, *args, storage_engine=PgStorage(name), workers=1, **kwargs
30
- )
31
+ def __init__(self, *args, **kwargs):
32
+ if not hasattr(self, "name"):
33
+ name = str(self.uid)
34
+ super().__init__(name, storage_engine=PgStorage(name), **kwargs) # , workers=2
35
+
36
+ async def preload(self):
37
+ if not (session := await Session.get_or_none(id=self.uid).prefetch_related("api")):
38
+ app = await App[20373304]
39
+ username, _ = await Username.get_or_create(id=self.uid)
40
+ bt = self.bot_token and self.bot_token.split(":")[1]
41
+ session = await Session.create(id=self.uid, api=app, user=username, is_bot=bt)
42
+ self.api_id = app.id
43
+ self.api_hash = app.hsh
44
+ await session.fetch_related("api")
45
+ self.storage.session = session
46
+
47
+ async def start(self, use_qr: bool = False, except_ids: list[int] = None):
48
+ if not self.is_connected:
49
+ await self.preload()
50
+ try:
51
+ return await super().start(use_qr=use_qr, except_ids=except_ids or [])
52
+ except (AuthKeyUnregistered, Unauthorized) as e:
53
+ await self.storage.session.delete()
54
+ raise e
55
+ return self
31
56
 
32
57
  async def send(
33
58
  self,
@@ -64,6 +89,7 @@ class BaseClient(Client, metaclass=SingleMeta):
64
89
  self.dispatcher.groups[g] = []
65
90
  self.dispatcher.groups = OrderedDict(sorted(self.dispatcher.groups.items()))
66
91
  self.dispatcher.groups[g].append(handler)
92
+ self.storage.session.state |= {uid: {"waiting_for": topic}}
67
93
  #
68
94
  while past < timeout:
69
95
  if txt := self.storage.session.state.get(uid, {}).pop(topic, None):
@@ -0,0 +1,39 @@
1
+ from pyro_client.client.base import BaseClient, AuthTopic
2
+ from pyro_client.loader import TOKEN
3
+
4
+
5
+ class BotClient(BaseClient):
6
+ def __new__(cls, bid: int | str) -> "BotClient":
7
+ """
8
+ :param bid: int | str - Если для такого bot_id в бд есть Session с его токеном в is_bot - можно просто id: int
9
+ если нет - нужно передавать весь токен, что б Сессия в бд создалась.
10
+ """
11
+ if isinstance(bid, str):
12
+ bid = int(bid.split(":")[0])
13
+ return super().__new__(cls, bid)
14
+
15
+ def __init__(self, bid: int | str):
16
+ bt = isinstance(bid, str) and ":" in bid and bid
17
+ super().__init__(bid, bot_token=bt or None)
18
+
19
+ async def wait_auth_from(self, uid: int, topic: AuthTopic, past: int = 0, timeout: int = 60) -> str:
20
+ return await super().wait_from(uid, topic, past, timeout)
21
+
22
+
23
+ async def main():
24
+ from x_model import init_db
25
+ from pyro_client.loader import TORM
26
+
27
+ _ = await init_db(TORM, True)
28
+
29
+ bc: BotClient = BotClient(6806432376)
30
+ bc1: BotClient = BotClient(TOKEN)
31
+ await bc.start()
32
+ await bc1.start()
33
+ await bc.stop()
34
+
35
+
36
+ if __name__ == "__main__":
37
+ from asyncio import run
38
+
39
+ run(main())
@@ -5,20 +5,25 @@ from os.path import dirname
5
5
  from pydantic import BaseModel, Field
6
6
  from pyrogram import enums
7
7
  from pyrogram.enums import ClientPlatform
8
- from pyrogram.errors import BadRequest, SessionPasswordNeeded, AuthKeyUnregistered, Unauthorized
8
+ from pyrogram.errors import BadRequest, SessionPasswordNeeded
9
9
  from pyrogram.session import Auth, Session as PyroSession
10
10
  from pyrogram.types import Message, User, SentCode, InlineKeyboardButton, KeyboardButton
11
- from x_auth.models import Session, Username, Proxy
11
+ from x_auth.models import Username, Proxy
12
12
 
13
13
  from pyro_client.client.base import BaseClient, AuthTopic
14
14
  from pyro_client.client.bot import BotClient
15
- from pyro_client.loader import WSToken, TOKEN
15
+ from pyro_client.loader import WSToken
16
16
 
17
17
  vers: dict[ClientPlatform, str] = {
18
18
  ClientPlatform.IOS: "18.5",
19
19
  ClientPlatform.ANDROID: "16",
20
20
  }
21
21
 
22
+ devs: dict[ClientPlatform, str] = {
23
+ ClientPlatform.IOS: "iPhone 17 Air",
24
+ ClientPlatform.ANDROID: "Tesla Phone",
25
+ }
26
+
22
27
 
23
28
  class Prx(BaseModel):
24
29
  scheme: str = "socks5"
@@ -31,31 +36,24 @@ class Prx(BaseModel):
31
36
  class UserClient(BaseClient):
32
37
  bot: BotClient
33
38
 
34
- def __init__(self, sess: Session, bot):
39
+ def __init__(self, uid: int, bot: BotClient = None):
35
40
  self.bot = bot
36
- super().__init__(
37
- sess.id,
38
- sess.api.id,
39
- sess.api.hsh,
40
- device_model="iPhone 16e",
41
- app_version=sess.api.ver,
42
- system_version=vers.get(sess.api.platform),
43
- client_platform=sess.api.platform,
44
- proxy=sess.proxy and sess.proxy.dict(),
45
- )
41
+ super().__init__(uid)
42
+
43
+ async def preload(self):
44
+ await super().preload()
45
+ self.device_model = devs[self.storage.session.api.platform]
46
+ self.app_version = self.storage.session.api.ver
47
+ self.system_version = vers[self.storage.session.api.platform]
48
+ self.client_platform = self.storage.session.api.platform
49
+ # await self.storage.session.fetch_related("proxy")
50
+ # self.proxy: Proxy = self.storage.session.proxy and self.storage.session.proxy.dict()
46
51
 
47
52
  async def start(self, use_qr: bool = False, except_ids: list[int] = None):
48
53
  if not self.bot.is_connected:
49
54
  await self.bot.start()
50
- # dcs = await self.bot.invoke(GetConfig())
51
- try:
52
- await super().start(use_qr=use_qr, except_ids=except_ids or [])
53
- await self.send("im ok")
54
- except AuthKeyUnregistered as e:
55
- await self.storage.session.delete()
56
- raise e
57
- except (AuthKeyUnregistered, Unauthorized) as e:
58
- raise e
55
+ await super().start(use_qr, except_ids)
56
+ # await self.send("/start", self.bot.uid)
59
57
 
60
58
  async def ask_for(
61
59
  self, topic: AuthTopic, question: str, btns: list[InlineKeyboardButton, KeyboardButton] = None
@@ -86,7 +84,7 @@ class UserClient(BaseClient):
86
84
  return v
87
85
  return 2
88
86
 
89
- async def authorize(self, sent_code: SentCode = None) -> User:
87
+ async def authorize(self, sent_code: SentCode = None) -> User | None:
90
88
  sent_code_desc = {
91
89
  enums.SentCodeType.APP: "Telegram app",
92
90
  enums.SentCodeType.SMS: "SMS",
@@ -136,19 +134,16 @@ class UserClient(BaseClient):
136
134
  except BadRequest as e:
137
135
  await self.send(e.MESSAGE)
138
136
  self.password = None
139
- else:
140
- raise Exception("User does not sent code")
137
+ else:
138
+ raise Exception("User does not sent code")
141
139
  if isinstance(signed_in, User):
142
- await self.send("✅", self.bot.me.id)
140
+ await self.send("✅")
143
141
  await self.storage.save()
144
142
  return signed_in
145
143
 
146
144
  if not signed_in:
147
145
  await self.receive("No registered such phone number")
148
-
149
- async def stop(self, block: bool = True):
150
- await super().stop(block)
151
- await self.bot.stop(block)
146
+ return None
152
147
 
153
148
  async def session_update(self, dc: int):
154
149
  await self.session.stop()
@@ -170,21 +165,21 @@ class UserClient(BaseClient):
170
165
 
171
166
 
172
167
  async def main():
173
- from x_auth import models
174
168
  from x_model import init_db
169
+ from pyro_client.loader import TORM
175
170
 
176
- from pyro_client.loader import WSToken, PG_DSN
177
-
178
- _ = await init_db(PG_DSN, models, True)
171
+ _ = await init_db(TORM, True)
179
172
 
180
173
  logging.basicConfig(level=logging.INFO)
181
174
 
182
- await models.Proxy.load_list(WSToken)
175
+ # await models.Proxy.load_list(WSToken)
183
176
  # session = await models.Session.filter(is_bot__isnull=True).order_by("-date").prefetch_related("proxy").first()
184
- bc: BotClient = await BotClient(TOKEN)
185
- uc: UserClient = await UserClient(5547330178, bc)
177
+ bc: BotClient = BotClient(6806432376)
178
+ uc: UserClient = UserClient(7314099964, bc)
186
179
  # try:
187
180
  await uc.start()
181
+ # b = await uc.resolve_peer('xyncnetbot')
182
+ await uc.send("/start", bc.me.username)
188
183
  # except Exception as e:
189
184
  # print(e.MESSAGE)
190
185
  # await uc.send(e.MESSAGE)
@@ -1,11 +1,19 @@
1
1
  from dotenv import load_dotenv
2
2
  from os import getenv as env
3
3
 
4
+ from x_auth import models
5
+
4
6
  load_dotenv()
5
7
 
6
8
  API_ID = env("API_ID")
7
9
  API_HASH = env("API_HASH")
8
10
  PG_DSN = f"postgres://{env('POSTGRES_USER')}:{env('POSTGRES_PASSWORD')}@{env('POSTGRES_HOST', 'xyncdbs')}:" \
9
11
  f"{env('POSTGRES_PORT', 5432)}/{env('POSTGRES_DB', env('POSTGRES_USER'))}"
12
+ TORM = {
13
+ "connections": {"default": PG_DSN},
14
+ "apps": {"models": {"models": [models]}},
15
+ "use_tz": False,
16
+ "timezone": "UTC",
17
+ }
10
18
  TOKEN = env("TOKEN")
11
19
  WSToken = env("WST")
@@ -1,34 +1,32 @@
1
1
  import time
2
- from typing import Any, Literal
2
+ from typing import Any
3
3
 
4
4
  from pyrogram import raw, utils
5
5
  from pyrogram.storage import Storage
6
+ from x_auth.enums import PeerType
6
7
  from x_auth.models import Username, Version, Session, Peer, UpdateState
7
8
 
8
9
 
9
- def get_input_peer(peer_id: int, access_hash: int, peer_type: Literal["user", "bot", "group", "channel", "supergroup"]):
10
- if peer_type in ["user", "bot"]:
10
+ def get_input_peer(peer_id: int, access_hash: int, peer_type: PeerType):
11
+ if peer_type in [PeerType.user, PeerType.bot]:
11
12
  return raw.types.InputPeerUser(user_id=peer_id, access_hash=access_hash)
12
-
13
- if peer_type == "group":
13
+ if peer_type == PeerType.group:
14
14
  return raw.types.InputPeerChat(chat_id=-peer_id)
15
-
16
- if peer_type in ["channel", "supergroup"]:
15
+ if peer_type in [PeerType.channel, PeerType.supergroup]:
17
16
  return raw.types.InputPeerChannel(channel_id=utils.get_channel_id(peer_id), access_hash=access_hash)
18
-
19
- raise ValueError(f"Invalid peer type: {peer_type}")
17
+ raise ValueError(f"Invalid peer type: {peer_type.name}")
20
18
 
21
19
 
22
20
  class PgStorage(Storage):
23
21
  VERSION = 1
24
- USERNAME_TTL = 8 * 60 * 60
22
+ USERNAME_TTL = 30 * 24 * 3600
25
23
  session: Session
26
-
27
- # me_id: int
24
+ sid: int
28
25
 
29
26
  async def open(self):
30
- # self.me_id = int((uid_dc := self.name.split("_")).pop(0))
31
- self.session = await Session[self.name]
27
+ self.sid = int(self.name)
28
+ if not self.session:
29
+ self.session = await Session[self.sid]
32
30
 
33
31
  async def save(self):
34
32
  await self.date(int(time.time()))
@@ -36,14 +34,14 @@ class PgStorage(Storage):
36
34
  async def close(self): ...
37
35
 
38
36
  async def delete(self):
39
- await Session.filter(id=self.name).delete()
37
+ await Session.filter(id=self.sid).delete()
40
38
 
41
39
  async def update_peers(self, peers: list[tuple[int, int, str, str]]):
42
40
  for peer in peers:
43
41
  uid, ac_hsh, typ, phone = peer
44
42
  un, _ = await Username.update_or_create(phone and {"phone": phone}, id=uid)
45
43
  await Peer.update_or_create(
46
- {"username": un, "type": typ, "phone_number": phone}, session_id=self.name, id=ac_hsh
44
+ {"username": un, "type": PeerType[typ], "phone_number": phone}, session_id=self.sid, id=ac_hsh
47
45
  )
48
46
 
49
47
  async def update_usernames(self, usernames: list[tuple[int, list[str]]]):
@@ -51,37 +49,45 @@ class PgStorage(Storage):
51
49
  for username in user_list:
52
50
  await Username.update_or_create({"username": username}, id=telegram_id)
53
51
 
54
- async def get_peer_by_id(self, uin: int | str):
55
- peer = await (
56
- Peer.get(session_id=self.name, username_id=uin) if isinstance(uin, int) else self.get_peer_by_username(uin)
57
- )
52
+ async def get_peer_by_id(self, uid: int | str):
53
+ if isinstance(uid, str):
54
+ if uid.isnumeric():
55
+ uid = int(uid)
56
+ else:
57
+ return await self.get_peer_by_username(uid)
58
+ if not (peer := await Peer.get_or_none(session_id=self.sid, username_id=uid)):
59
+ raise KeyError(f"Peer#{uid} not found")
58
60
  if peer.last_update_on:
59
61
  if abs(time.time() - peer.last_update_on.timestamp()) > self.USERNAME_TTL:
60
- raise KeyError(f"Username expired: {uin}")
62
+ raise KeyError(f"Username expired: {uid}")
61
63
  return get_input_peer(peer.username_id, peer.id, peer.type)
62
64
 
63
65
  async def get_peer_by_username(self, username: str):
64
- return await Peer.get(session_id=self.name, username__username=username)
66
+ if not (peer := await Peer.get_or_none(session_id=self.sid, username__username=username)):
67
+ if not (user := await Username.get_or_none(username=username)):
68
+ raise KeyError(f"Username: {username} not found")
69
+ return await self.get_peer_by_id(user.id)
70
+ return get_input_peer(peer.username_id, peer.id, peer.type)
65
71
 
66
- async def update_state(self, value: tuple[int, int, int, int, int] = object):
72
+ async def update_state(self, value: tuple[int, int, int, int, int] = ...):
67
73
  if value is None:
68
- return await UpdateState.filter(session_id=self.name)
74
+ return await UpdateState.filter(session_id=self.sid)
69
75
  elif isinstance(value, int):
70
- await UpdateState.filter(session_id=self.name, id=value).delete()
76
+ await UpdateState.filter(session_id=self.sid, id=value).delete()
71
77
  else:
72
78
  sid, pts, qts, date, seq = value
73
79
  await UpdateState.get_or_create(
74
- {"pts": pts, "qts": qts, "date": date, "seq": seq}, session_id=self.name, id=sid
80
+ {"pts": pts, "qts": qts, "date": date, "seq": seq}, session_id=self.sid, id=sid
75
81
  )
76
82
 
77
83
  async def get_peer_by_phone_number(self, phone_number: str):
78
84
  attrs = "id", "access_hash", "type"
79
- if not (peer := await Peer.get_or_none(session_id=self.name, phone_number=phone_number).values_list(*attrs)):
80
- peer = await Peer.get(session_id=self.name, username__phone=phone_number).values_list(*attrs)
85
+ if not (peer := await Peer.get_or_none(session_id=self.sid, phone_number=phone_number).values_list(*attrs)):
86
+ peer = await Peer.get(session_id=self.sid, username__phone=phone_number).values_list(*attrs)
81
87
  return get_input_peer(*peer)
82
88
 
83
89
  async def _get(self, attr: str):
84
- return await Session.get(id=self.name).values_list(attr, flat=True)
90
+ return await Session.get(id=self.sid).values_list(attr, flat=True)
85
91
 
86
92
  async def _set(self, attr: str, value):
87
93
  # if "__" in attr:
@@ -90,40 +96,42 @@ class PgStorage(Storage):
90
96
  # rel.__setattr__(attr, value)
91
97
  # await rel.save()
92
98
  # else:
93
- await Session.update_or_create({attr: value}, id=self.name)
99
+ await Session.update_or_create({attr: value}, id=self.sid)
94
100
 
95
- async def _accessor(self, attr: str, value: Any = object):
96
- if value is object:
101
+ async def _accessor(self, attr: str, value: Any = ...):
102
+ if value is ...:
97
103
  return await self._get(attr)
104
+ # elif attr == ...:
105
+ # return await self._set(attr, ...)
98
106
  else:
99
107
  await self._set(attr, value)
100
108
 
101
- async def dc_id(self, value: int = object):
109
+ async def dc_id(self, value: int = ...):
102
110
  return await self._accessor("dc_id", value)
103
111
 
104
- async def api_id(self, value: int = object):
112
+ async def api_id(self, value: int = ...):
105
113
  return await self._accessor("api_id", value)
106
114
 
107
- async def test_mode(self, value: bool = object):
115
+ async def test_mode(self, value: bool = ...):
108
116
  return await self._accessor("test_mode", value)
109
117
 
110
- async def auth_key(self, value: bytes = object):
118
+ async def auth_key(self, value: bytes = ...):
111
119
  return await self._accessor("auth_key", value)
112
120
 
113
- async def date(self, value: int = object):
121
+ async def date(self, value: int = ...):
114
122
  return await self._accessor("date", value)
115
123
 
116
- async def user_id(self, value: int = object):
124
+ async def user_id(self, value: int = ...):
117
125
  return await self._accessor("user_id", value)
118
126
 
119
- async def is_bot(self, value: bool = object):
120
- if value is not object:
127
+ async def is_bot(self, value: bool = ...):
128
+ if value is not ...:
121
129
  value = self.session.is_bot if value else None # dirty
122
130
  return bool(await self._accessor("is_bot", value))
123
131
 
124
132
  @staticmethod
125
- async def version(value: int = object):
126
- if value is object:
133
+ async def version(value: int = ...):
134
+ if value is ...:
127
135
  ver = await Version.first()
128
136
  return ver.number
129
137
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrogram-client
3
- Version: 0.0.5
3
+ Version: 0.0.7.dev2
4
4
  Author-email: Mike Artemiev <mixartemev@gmail.com>
5
5
  Project-URL: Homepage, https://gitlab.com/XyncNet/pyro-client
6
6
  Project-URL: Repository, https://gitlab.com/XyncNet/pyro-client
@@ -9,7 +9,6 @@ pyro_client/client/base.py
9
9
  pyro_client/client/bot.py
10
10
  pyro_client/client/dc.json
11
11
  pyro_client/client/file.py
12
- pyro_client/client/single.py
13
12
  pyro_client/client/user.py
14
13
  pyrogram_client.egg-info/PKG-INFO
15
14
  pyrogram_client.egg-info/SOURCES.txt
@@ -1,11 +0,0 @@
1
- from x_auth.models import Session
2
-
3
- from pyro_client.client.base import BaseClient, AuthTopic
4
-
5
-
6
- class BotClient(BaseClient):
7
- def __init__(self, sess: Session, _=None):
8
- super().__init__(sess.id, sess.api.id, sess.api.hsh, bot_token=f"{sess.id}:{sess.is_bot}")
9
-
10
- async def wait_auth_from(self, uid: int, topic: AuthTopic, past: int = 0, timeout: int = 60) -> str:
11
- return await super().wait_from(uid, topic, past, timeout)
@@ -1,40 +0,0 @@
1
- from tortoise.functions import Count
2
- from x_auth.models import Proxy, Session, Username, App
3
-
4
- from pyro_client.loader import WSToken
5
-
6
-
7
- class SingleMeta(type):
8
- _instances = {}
9
-
10
- async def __call__(cls, uid: int | str, bot=None):
11
- if cls not in cls._instances:
12
- prx = ...
13
- bt = None
14
- if isinstance(uid, str):
15
- if len(ub := uid.split(":")) == 2:
16
- uid, bt = ub
17
- prx = None
18
- if uid.isnumeric():
19
- uid = int(uid)
20
- sess = await cls._sess(uid, bt, prx)
21
- cls._instances[cls] = super().__call__(sess, bot)
22
- return cls._instances[cls]
23
-
24
- async def _sess(self, uid: int | str, bt: str = None, px: Proxy | None = ..., dc: int = 2) -> Session:
25
- username, _ = await Username.get_or_create(**{"id" if isinstance(uid, int) else "username": uid})
26
- if not (
27
- session := await Session.get_or_none(user=username, api__dc=dc) or await Session.get_or_none(id=username.id)
28
- ):
29
- if px is Ellipsis:
30
- await Proxy.load_list(WSToken)
31
- # await Proxy.get_replaced(WSToken)
32
- px = await Proxy.annotate(sc=Count("sessions")).filter(valid=True).order_by("sc", "-updated_at").first()
33
- if username.phone:
34
- # noinspection PyUnresolvedReferences
35
- dc = dc or self.get_dc()
36
- session = await Session.create(
37
- id=username.id, api=await App[20373304], user=username, dc_id=dc, proxy=px, is_bot=bt
38
- )
39
- await session.fetch_related("proxy", "api")
40
- return session