Skip to content

Commit

Permalink
1.1.28
Browse files Browse the repository at this point in the history
- Fix non-working param `share_link` in loader
- Assure logging bot is a member of logchat
- Do not store partial phone number in session, only ID
- Rework fast uploader so more types can be passed. For more information check code docstrings and typehints
- Rework installer so it properly displays which action is currently happening
- Fix `Series` not accepting one item
- Show upcoming commit in update and warn if update is not required
- Add reset to default button to config
- Merge `hikka_logger.py` with `test.py`
- Localization
- Allow opening options of specific mod via arguments in `.config`
- Add `add` and `remove` buttons to `Series` params
- Do not unload form immediately, if `ttl` param was passed explicitly
  • Loading branch information
hikariatama committed May 25, 2022
1 parent 673f4eb commit 3fc77b5
Show file tree
Hide file tree
Showing 13 changed files with 558 additions and 337 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## 🌑 Hikka 1.1.28

- Fix non-working param `share_link` in loader
- Assure logging bot is a member of logchat
- Do not store partial phone number in session, only ID
- Rework fast uploader so more types can be passed. For more information check code docstrings and typehints
- Rework installer so it properly displays which action is currently happening
- Fix `Series` not accepting one item
- Show upcoming commit in update and warn if update is not required
- Add reset to default button to config
- Merge `hikka_logger.py` with `test.py`
- Localization
- Allow opening options of specific mod via arguments in `.config`
- Add `add` and `remove` buttons to `Series` params
- Do not unload form immediately, if `ttl` param was passed explicitly

## 🌑 Hikka 1.1.27

- Reorder the steps of parsing in `loader.validators.Series`
Expand Down
13 changes: 6 additions & 7 deletions hikka/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@
and "OKTETO" not in os.environ
and "DOCKER" not in os.environ
):
print("🚫" * 30)
print("NEVER EVER RUN USERBOT FROM ROOT")
print("THIS IS THE THREAD FOR NOT ONLY YOUR DATA, ")
print("BUT ALSO FOR YOUR DEVICE ITSELF!")
print("🚫" * 30)
print("🚫" * 15)
print("You attempted to run Hikka on behalf of root user")
print("Please, create a new user and restart script")
print("If this action was intentional, pass --root argument instead")
print("🚫" * 15)
print()
print("TYPE force_insecure TO IGNORE THIS WARNING")
print("TYPE ANYTHING ELSE TO EXIT:")
print("Type force_insecure to ignore this warning")
if input("> ").lower() != "force_insecure":
sys.exit(1)

Expand Down
87 changes: 78 additions & 9 deletions hikka/fast_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def __init__(
async def next(self) -> Optional[bytes]:
if not self.remaining:
return None

result = await self.client._call(self.sender, self.request)
self.remaining -= 1
self.request.offset += self.stride
Expand Down Expand Up @@ -126,10 +127,12 @@ def __init__(
self.client = client
self.sender = sender
self.part_count = part_count

if big:
self.request = SaveBigFilePartRequest(file_id, index, part_count, b"")
else:
self.request = SaveFilePartRequest(file_id, index, b"")

self.stride = stride
self.previous = None
self.loop = loop
Expand Down Expand Up @@ -207,18 +210,27 @@ def get_part_count() -> int:
if remainder > 0:
remainder -= 1
return minimum + 1

return minimum

# The first cross-DC sender will export+import the authorization, so we always create it
# before creating any other senders.
self.senders = [
await self._create_download_sender(
file, 0, part_size, connections * part_size, get_part_count()
file,
0,
part_size,
connections * part_size,
get_part_count(),
),
*await asyncio.gather(
*[
self._create_download_sender(
file, i, part_size, connections * part_size, get_part_count()
file,
i,
part_size,
connections * part_size,
get_part_count(),
)
for i in range(1, connections)
]
Expand Down Expand Up @@ -295,7 +307,8 @@ async def _create_sender(self) -> MTProtoSender:
log.debug(f"Exporting auth to DC {self.dc_id}")
auth = await self.client(ExportAuthorizationRequest(self.dc_id))
self.client._init_request.query = ImportAuthorizationRequest(
id=auth.id, bytes=auth.bytes
id=auth.id,
bytes=auth.bytes,
)
req = InvokeWithLayerRequest(LAYER, self.client._init_request)
await sender.send(req)
Expand Down Expand Up @@ -344,12 +357,16 @@ async def download(

while part < part_count:
tasks = []

for sender in self.senders:
tasks.append(self.loop.create_task(sender.next()))

for task in tasks:
data = await task

if not data:
break

yield data
part += 1
log.debug(f"Part {part} downloaded")
Expand All @@ -376,10 +393,20 @@ async def _internal_transfer_to_telegram(
client: TelegramClient,
response: BinaryIO,
progress_callback: callable,
filename: str = "upload",
filename: Optional[str] = None,
) -> Tuple[TypeInputFile, int]:
file_id = helpers.generate_random_long()
file_size = os.path.getsize(response.name)
file_size = (
response.getbuffer().nbytes
if isinstance(response, io.BytesIO)
else os.path.getsize(response.name)
)

if not filename:
if isinstance(response, io.BytesIO) and getattr(response, "name", False):
filename = response.name
else:
filename = "unnamed"

hash_md5 = hashlib.md5()
uploader = ParallelTransferrer(client)
Expand All @@ -390,12 +417,16 @@ async def _internal_transfer_to_telegram(
r = progress_callback(response.tell(), file_size)
if inspect.isawaitable(r):
await r

if not is_large:
hash_md5.update(data)

if len(buffer) == 0 and len(data) == part_size:
await uploader.upload(data)
continue

new_len = len(buffer) + len(data)

if new_len >= part_size:
cutoff = part_size - len(buffer)
buffer.extend(data[:cutoff])
Expand All @@ -404,8 +435,10 @@ async def _internal_transfer_to_telegram(
buffer.extend(data[cutoff:])
else:
buffer.extend(data)

if len(buffer) > 0:
await uploader.upload(bytes(buffer))

await uploader.finish_upload()

return (
Expand All @@ -421,11 +454,27 @@ def _progressbar(progress: int) -> str:


async def download_file(
location: TypeLocation = None,
location: Union[Message, TypeLocation] = None,
progress_callback: callable = None,
message_object: Optional[Union[Message, InlineMessage]] = None,
_client: TelegramClient = None,
) -> BinaryIO:
"""
Uses multi-threading to quickly download file to Telegram servers
:param location: From where to download file? If it's not possible to do via fast_downloader
it will be downloaded through classic tools instead
:param progress_callback: Must be a synchronous or asynchronous function handling callback
You can instead pass `message_object`, Hikka will generate handler
for you
:param message_object: Must be a telethon message object or an instance, generated by callback
handler / form, which can be passed to `utils.answer`
"""
if getattr(location, "document", None):
location = location.document

if not hasattr(location, "size"):
return io.BytesIO(await _client._download_file(location, bytes))

size = location.size
dc_id, location = utils.get_input_location(location)

Expand Down Expand Up @@ -480,12 +529,27 @@ async def default_progress_callback(current: int, total: int):


async def upload_file(
file: BinaryIO = None,
file: Union[BinaryIO, bytes] = None,
progress_callback: callable = None,
filename: str = "upload",
filename: Optional[str] = None,
message_object: Optional[Union[Message, InlineMessage]] = None,
_client: TelegramClient = None,
) -> TypeInputFile:
"""
Uses multi-threading to quickly upload file to Telegram servers
:param file: Can be a BinaryIO (file handler, `io` handler) or a bytes
If bytes were passed, they will be converted to BytesIO
If passed object has a filename, it can be parsed instead of `filename`
:param progress_callback: Must be a synchronous or asynchronous function handling callback
You can instead pass `message_object`, Hikka will generate handler
for you
:param filename: If your `file` has no attribute `name` or you want to override it, pass here
a valid string with filename
:param message_object: Must be a telethon message object or an instance, generated by callback
handler / form, which can be passed to `utils.answer`
"""
if not hasattr(file, "read"):
file = io.BytesIO(file)

ratelimiter = time.time() + 3

Expand Down Expand Up @@ -513,7 +577,12 @@ async def default_progress_callback(current: int, total: int):
progress_callback = default_progress_callback

res = (
await _internal_transfer_to_telegram(_client, file, progress_callback, filename)
await _internal_transfer_to_telegram(
_client,
file,
progress_callback,
filename,
)
)[0]

if message_object is not None:
Expand Down
2 changes: 1 addition & 1 deletion hikka/inline/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ async def form(
if not any(
any("callback" in button or "input" in button for button in row)
for row in reply_markup
):
) and not ttl:
del self._forms[form_uid]
logger.debug(
f"Unloading form {form_uid}, because it "
Expand Down
8 changes: 7 additions & 1 deletion hikka/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,16 @@ def _get_token(self):
self._get_api_token()

async def save_client_session(self, client: TelegramClient):
if hasattr(client, "_tg_id"):
id_ = client._tg_id
else:
id_ = (await client.get_me()).id
client._tg_id = id_

session = SQLiteSession(
os.path.join(
self.arguments.data_root or BASE_DIR,
f"hikka-+{'x' * (len(client.phone) - 5)}{client.phone[-4:]}-{(await client.get_me()).id}",
f"hikka-{id_}",
)
)

Expand Down
Loading

0 comments on commit 3fc77b5

Please sign in to comment.