初始化 telegram-downloader 并接入群晖 CI/CD
部署到群晖 / deploy (push) Failing after 10m45s

This commit is contained in:
yuming
2026-04-22 21:29:03 +08:00
commit cf40343c51
153 changed files with 33376 additions and 0 deletions
View File
View File
+71
View File
@@ -0,0 +1,71 @@
"""test app"""
import os
import sys
import unittest
from unittest import mock
import module.app
from module.app import Application, ChatDownloadConfig, DownloadStatus
sys.path.append("..") # Adds higher directory to python modules path.
class AppTestCase(unittest.TestCase):
@classmethod
def tearDownClass(cls):
config_test = os.path.join(os.path.abspath("."), "config_test.yaml")
data_test = os.path.join(os.path.abspath("."), "data_test.yaml")
if os.path.exists(config_test):
os.remove(config_test)
if os.path.exists(data_test):
os.remove(data_test)
def test_app(self):
app = Application("", "")
self.assertEqual(app.save_path, os.path.join(os.path.abspath("."), "downloads"))
self.assertEqual(app.proxy, {})
self.assertEqual(app.restart_program, False)
app.chat_download_config[123] = ChatDownloadConfig()
app.chat_download_config[123].last_read_message_id = 13
app.chat_download_config[123].node.download_status[
6
] = DownloadStatus.Downloading
app.chat_download_config[123].ids_to_retry.append(7)
# download success
app.chat_download_config[123].node.download_status[
8
] = DownloadStatus.SuccessDownload
app.chat_download_config[123].finish_task += 1
# download success
app.chat_download_config[123].node.download_status[
10
] = DownloadStatus.SuccessDownload
app.chat_download_config[123].finish_task += 1
# not exist message
app.chat_download_config[123].node.download_status[
13
] = DownloadStatus.SuccessDownload
app.config["chat"] = [{"chat_id": 123, "last_read_message_id": 5}]
app.update_config(False)
self.assertEqual(
app.chat_download_config[123].last_read_message_id + 1,
app.config["chat"][0]["last_read_message_id"],
)
self.assertEqual(
[6, 7],
app.app_data["chat"][0]["ids_to_retry"],
)
@mock.patch("__main__.__builtins__.open", new_callable=mock.mock_open)
@mock.patch("module.app.yaml", autospec=True)
def test_update_config(self, mock_yaml, mock_open):
app = Application("", "")
app.config_file = "config_test.yaml"
app.app_data_file = "data_test.yaml"
app.config["chat"] = [{"chat_id": 123, "last_read_message_id": 0}]
app.update_config()
mock_open.assert_called_with("data_test.yaml", "w", encoding="utf-8")
+203
View File
@@ -0,0 +1,203 @@
import datetime
import platform
from pyrogram.file_id import PHOTO_TYPES, FileType
class Chat:
def __init__(self, chat_id, chat_title):
self.id = chat_id
self.title = chat_title
class Date:
def __init__(self, date):
self.date = date
def strftime(self, str) -> str:
return ""
class MockMessage:
def __init__(self, **kwargs):
self.id = kwargs.get("id")
self.media = kwargs.get("media")
self.audio = kwargs.get("audio", None)
self.document = kwargs.get("document", None)
self.photo = kwargs.get("photo", None)
self.video = kwargs.get("video", None)
self.voice = kwargs.get("voice", None)
self.video_note = kwargs.get("video_note", None)
self.media_group_id = kwargs.get("media_group_id", None)
self.caption = kwargs.get("caption", None)
self.text = kwargs.get("text", None)
self.empty = kwargs.get("empty", False)
self.from_user = kwargs.get("from_user", None)
self.reply_to_message_id = kwargs.get("reply_to_message_id", None)
self.caption_entities = kwargs.get("caption_entities", None)
if kwargs.get("dis_chat") == None:
self.chat = Chat(
kwargs.get("chat_id", None), kwargs.get("chat_title", None)
)
else:
self.chat = kwargs.get("chat", None)
self.date: datetime = None
if kwargs.get("date") != None:
self.date = kwargs["date"]
class MockUser:
def __init__(self, **kwargs):
self.id = kwargs.get("id", 0)
self.username = kwargs.get("username", "")
class MockAudio:
def __init__(self, **kwargs):
self.file_name = kwargs["file_name"]
self.mime_type = kwargs["mime_type"]
self.file_id = "AUDIO"
if kwargs.get("file_size"):
self.file_size = kwargs["file_size"]
else:
self.file_size = 1024
class MockDocument:
def __init__(self, **kwargs):
self.file_name = kwargs["file_name"]
self.mime_type = kwargs["mime_type"]
self.file_id = "DOCUMENT"
if kwargs.get("file_size"):
self.file_size = kwargs["file_size"]
else:
self.file_size = 1024
class MockPhoto:
def __init__(self, **kwargs):
self.date = kwargs["date"]
self.file_unique_id = kwargs["file_unique_id"]
self.file_id = "PHOTO"
if kwargs.get("file_size"):
self.file_size = kwargs["file_size"]
else:
self.file_size = 1024
class MockVoice:
def __init__(self, **kwargs):
self.mime_type = kwargs["mime_type"]
self.date = kwargs["date"]
self.file_id = "VOICE"
if kwargs.get("file_size"):
self.file_size = kwargs["file_size"]
else:
self.file_size = 1024
class MockVideo:
def __init__(self, **kwargs):
self.file_name = kwargs.get("file_name")
self.mime_type = kwargs["mime_type"]
self.file_id = "VIDEO"
if kwargs.get("file_size"):
self.file_size = kwargs["file_size"]
else:
self.file_size = 1024
if kwargs.get("width"):
self.width = kwargs["width"]
else:
self.width = 1920
if kwargs.get("height"):
self.height = kwargs["height"]
else:
self.height = 1080
if kwargs.get("duration"):
self.duration = kwargs["duration"]
else:
self.duration = 1024
class MockVideoNote:
def __init__(self, **kwargs):
self.mime_type = kwargs["mime_type"]
self.file_id = "VIDEO_NOTE"
self.date = kwargs["date"]
def platform_generic_path(_path: str) -> str:
platform_specific_path: str = _path
if platform.system() == "Windows":
platform_specific_path = platform_specific_path.replace("/", "\\")
return platform_specific_path
def get_file_type(file_id: str):
if file_id == "THUMBNAIL":
return FileType.THUMBNAIL
elif file_id == "CHAT_PHOTO":
return FileType.CHAT_PHOTO
elif file_id == "PHOTO":
return FileType.PHOTO
elif file_id == "VOICE":
return FileType.VOICE
elif file_id == "VIDEO":
return FileType.VIDEO
elif file_id == "DOCUMENT":
return FileType.DOCUMENT
elif file_id == "ENCRYPTED":
return FileType.ENCRYPTED
elif file_id == "TEMP":
return FileType.TEMP
elif file_id == "STICKER":
return FileType.STICKER
elif file_id == "AUDIO":
return FileType.AUDIO
elif file_id == "ANIMATION":
return FileType.ANIMATION
elif file_id == "ENCRYPTED_THUMBNAIL":
return FileType.ENCRYPTED_THUMBNAIL
elif file_id == "WALLPAPER":
return FileType.WALLPAPER
elif file_id == "VIDEO_NOTE":
return FileType.VIDEO_NOTE
elif file_id == "SECURE_RAW":
return FileType.SECURE_RAW
elif file_id == "SECURE":
return FileType.SECURE
elif file_id == "BACKGROUND":
return FileType.BACKGROUND
elif file_id == "DOCUMENT_AS_FILE":
return FileType.DOCUMENT_AS_FILE
raise ValueError("error file id!")
def get_extension(file_id: str, mime_type: str, dot: bool = True):
file_type = get_file_type(file_id=file_id)
guessed_extension = ""
if file_type in PHOTO_TYPES:
extension = "jpg"
elif file_type == FileType.VOICE:
extension = guessed_extension or "ogg"
elif file_type in (FileType.VIDEO, FileType.ANIMATION, FileType.VIDEO_NOTE):
extension = guessed_extension or "mp4"
elif file_type == FileType.DOCUMENT:
extension = guessed_extension or "zip"
elif file_type == FileType.STICKER:
extension = guessed_extension or "webp"
elif file_type == FileType.AUDIO:
extension = guessed_extension or "mp3"
else:
extension = "unknown"
if dot:
extension = "." + extension
return extension
File diff suppressed because it is too large Load Diff
View File
+55
View File
@@ -0,0 +1,55 @@
"""Test Crypto"""
import sys
import unittest
from utils.crypto import AesBase64
sys.path.append("..") # Adds higher directory to python modules path.
class TestAesBase64(unittest.TestCase):
def test_aes_base64_encryption(self):
key = "This is a key123"
iv = "This is an iv456"
aes = AesBase64(key, iv)
content = "Some text for encryption."
encrypted_content = aes.encrypt(content)
decrypted_content = aes.decrypt(encrypted_content)
self.assertEqual(content, decrypted_content)
def test_aes_base64_encryption_with_special_characters(self):
key = "Special!@#$%^&*("
iv = "Characters123456"
aes = AesBase64(key, iv)
content = "Text with special characters!@#$%^&*()_+-=[]{}|;"
encrypted_content = aes.encrypt(content)
decrypted_content = aes.decrypt(encrypted_content)
self.assertEqual(content, decrypted_content)
def test_aes_base64_encryption_with_empty_string(self):
key = "Empty string tes"
iv = "1234567890123456"
aes = AesBase64(key, iv)
content = ""
encrypted_content = aes.encrypt(content)
decrypted_content = aes.decrypt(encrypted_content)
self.assertEqual(content, decrypted_content)
def test_aes_base64_pkcs7padding(self):
key = "Test padding key"
iv = "1234567890123456"
aes = AesBase64(key, iv)
content = "Test padding."
padded_content = aes.pkcs7padding(content)
self.assertEqual(len(padded_content) % 16, 0)
self.assertEqual(padded_content[-1], chr(16 - len(content) % 16))
def test_aes_base64_pkcs7unpadding(self):
key = "Test unpadding key"
iv = "1234567890123456"
aes = AesBase64(key, iv)
content = "Test unpadding."
padded_content = aes.pkcs7padding(content)
unpadded_content = aes.pkcs7unpadding(padded_content)
self.assertEqual(unpadded_content, content)
+40
View File
@@ -0,0 +1,40 @@
"""Unittest module for media downloader."""
import os
import sys
import tempfile
import unittest
from pathlib import Path
import mock
sys.path.append("..") # Adds higher directory to python modules path.
from utils.file_management import get_next_name, manage_duplicate_file
class FileManagementTestCase(unittest.TestCase):
def setUp(self):
self.this_dir = os.path.dirname(os.path.abspath(__file__))
self.test_file = os.path.join(self.this_dir, "file-test.txt")
self.test_file_copy_1 = os.path.join(self.this_dir, "file-test-copy1.txt")
self.test_file_copy_2 = os.path.join(self.this_dir, "file-test-copy2.txt")
f = open(self.test_file, "w+")
f.write("dummy file")
f.close()
Path(self.test_file_copy_1).touch()
Path(self.test_file_copy_2).touch()
def test_get_next_name(self):
result = get_next_name(self.test_file)
excepted_result = os.path.join(self.this_dir, "file-test-copy3.txt")
self.assertEqual(result, excepted_result)
def test_manage_duplicate_file(self):
result = manage_duplicate_file(self.test_file_copy_2)
self.assertEqual(result, self.test_file_copy_1)
result1 = manage_duplicate_file(self.test_file_copy_1)
self.assertEqual(result1, self.test_file_copy_1)
def tearDown(self):
os.remove(self.test_file)
os.remove(self.test_file_copy_1)
+450
View File
@@ -0,0 +1,450 @@
"""Unittest module for media downloader."""
import sys
import unittest
from datetime import datetime
import mock
from module.filter import Filter, MetaData
from module.pyrogram_extension import set_meta_data
from tests.test_common import (
Chat,
Date,
MockAudio,
MockDocument,
MockMessage,
MockPhoto,
MockUser,
MockVideo,
MockVideoNote,
MockVoice,
get_extension,
)
from utils.format import replace_date_time
sys.path.append("..") # Adds higher directory to python modules path.
def filter_exec(download_filter: Filter, filter_str: str) -> bool:
filter_str = replace_date_time(filter_str)
return download_filter.exec(filter_str)
def check_filter_exec(download_filter: Filter, filter_str: str) -> bool:
filter_str = replace_date_time(filter_str)
return download_filter.check_filter(filter_str)
@mock.patch("module.pyrogram_extension.get_extension", new=get_extension)
class FilterTestCase(unittest.TestCase):
def test_string_filter(self):
download_filter = Filter()
self.assertRaises(ValueError, filter_exec, download_filter, "213")
meta = MetaData()
message = MockMessage(
id=5,
media=True,
date=datetime(2022, 8, 5, 14, 35, 12),
chat_title="test2",
caption=None,
video=MockVideo(
mime_type="video/mp4",
file_size=1024 * 1024 * 10,
file_name="test.mp4",
width=1920,
height=1080,
duration=35,
),
from_user=MockUser(
username="coco",
id=123,
),
)
set_meta_data(meta, message)
self.assertEqual(meta.message_id, 5)
self.assertEqual(meta.message_date, datetime(2022, 8, 5, 14, 35, 12))
self.assertEqual(meta.message_caption, "")
self.assertEqual(meta.media_file_size, 1024 * 1024 * 10)
self.assertEqual(meta.media_width, 1920)
self.assertEqual(meta.media_height, 1080)
self.assertEqual(meta.media_file_name, "test.mp4")
self.assertEqual(meta.media_duration, 35)
self.assertEqual(meta.media_type, "video")
self.assertEqual(meta.file_extension, "mp4")
download_filter.set_meta_data(meta)
self.assertEqual(filter_exec(download_filter, "media_file_size == 1"), False)
self.assertEqual(filter_exec(download_filter, "media_file_size > 1024"), True)
# str
self.assertEqual(
filter_exec(download_filter, "media_file_name == 'test.mp4'"), True
)
self.assertEqual(
filter_exec(download_filter, "media_file_name == 'test2.mp4'"), False
)
# re str
self.assertEqual(
filter_exec(download_filter, "media_file_name == r'test.*mp4'"), True
)
self.assertEqual(
filter_exec(download_filter, "media_file_name == r'test\.*mp4'"), True
)
self.assertEqual(
filter_exec(download_filter, "media_file_name == r'test2.*mp4'"), False
)
self.assertEqual(
filter_exec(download_filter, "media_file_name != r'test2.*mp4'"), True
)
self.assertEqual(
filter_exec(download_filter, "media_file_name != r'test2.*mp4'"), True
)
# int
self.assertEqual(filter_exec(download_filter, "media_duration > 60"), False)
self.assertEqual(filter_exec(download_filter, "media_duration <= 60"), True)
self.assertEqual(
filter_exec(
download_filter, "media_width >= 1920 and media_height >= 1080"
),
True,
)
self.assertEqual(
filter_exec(download_filter, "media_width >= 2560 && media_height >= 1440"),
False,
)
self.assertEqual(
filter_exec(
download_filter,
"media_width >= 2560 && media_height >= 1440 or media_file_name == 'test.mp4'",
),
True,
)
# datetime
# 2020.03
self.assertEqual(
filter_exec(
download_filter, "message_date >= 2022.03 and message_date <= 2022.08"
),
False,
)
self.assertEqual(
filter_exec(
download_filter, "message_date >= 2022.03 and message_date <= 2022.09"
),
True,
)
# 2020.03.04
self.assertEqual(
filter_exec(
download_filter,
"message_date >= 2022.03.04 and message_date <= 2022.03.08",
),
False,
)
self.assertEqual(
filter_exec(
download_filter,
"message_date >= 2022.03.04 and message_date <= 2022.08.06",
),
True,
)
# 2020.03.04 14:50
self.assertEqual(
filter_exec(
download_filter,
"message_date >= 2022.03.04 14:50 and message_date <= 2022.03.08",
),
False,
)
self.assertEqual(
filter_exec(
download_filter,
"message_date >= 2022.03.04 and message_date <= 2022.08.05 14:36",
),
True,
)
# 2020.03.04 14:50:15
self.assertEqual(
filter_exec(
download_filter,
"message_date >= 2022.03.04 14:50:15 and message_date <= 2022.03.08",
),
False,
)
self.assertEqual(
filter_exec(
download_filter,
"message_date >= 2022.03.04 14:50:15 and message_date <= 2022.08.05 14:35:12",
),
True,
)
# test not exist value
self.assertRaises(
ValueError,
filter_exec,
download_filter,
"message_date >= 2022.03.04 && message_date <= 2022.08.06 && not_exist == True",
)
download_filter.set_debug(True)
# test file_size
self.assertEqual(filter_exec(download_filter, "file_size >= 10MB"), True)
self.assertEqual(filter_exec(download_filter, "file_size >= 11MB"), False)
self.assertEqual(filter_exec(download_filter, "file_size >= 11GB"), False)
self.assertEqual(filter_exec(download_filter, "file_size <= 11GB"), True)
self.assertEqual(
filter_exec(download_filter, "1024 * 1024 * 1024 * 11 == 11GB"), True
)
# test caption
self.assertEqual(filter_exec(download_filter, "caption == r'.*#test.*'"), False)
# test media_type
self.assertEqual(filter_exec(download_filter, "media_type == 'video'"), True)
self.assertEqual(filter_exec(download_filter, "media_type == 'audio'"), False)
self.assertEqual(
filter_exec(download_filter, "media_type == r'(video|audio)'"), True
)
self.assertEqual(
filter_exec(download_filter, "media_type != r'(video|audio)'"), False
)
# test file_extension
self.assertEqual(filter_exec(download_filter, "file_extension == 'mp4'"), True)
self.assertEqual(filter_exec(download_filter, "file_extension == 'mp3'"), False)
self.assertEqual(
filter_exec(download_filter, "file_extension == r'(mp4|mp3)'"), True
)
self.assertEqual(
filter_exec(download_filter, "file_extension != r'(mp4|mp3)'"), False
)
# test sender
self.assertEqual(filter_exec(download_filter, "sender_name == 'coco'"), True)
self.assertEqual(filter_exec(download_filter, "sender_id == 1"), False)
def test_null_obj(self):
download_filter = Filter()
meta = MetaData()
message = MockMessage(
id=5,
media=True,
date=datetime(2022, 8, 5, 14, 35, 12),
chat_title="test2",
caption=None,
video=MockPhoto(
file_size=1024 * 1024 * 10,
date=datetime(2019, 8, 5, 14, 35, 12),
file_unique_id="ADAVKJYIFV",
),
)
set_meta_data(meta, message)
download_filter.set_meta_data(meta)
# test media_duration
self.assertEqual(filter_exec(download_filter, "media_duration < 1"), False)
self.assertEqual(filter_exec(download_filter, "media_duration <= 1"), False)
self.assertEqual(filter_exec(download_filter, "media_duration != 1"), False)
self.assertEqual(filter_exec(download_filter, "media_duration == 1"), False)
def test_str_obj(self):
download_filter = Filter()
self.assertRaises(ValueError, filter_exec, download_filter, "213")
meta = MetaData()
message = MockMessage(
id=5,
media=True,
date=datetime(2022, 8, 5, 14, 35, 12),
chat_title="test2",
caption="#中文最吊 #哈啰",
video=MockVideo(
mime_type="video/mp4",
file_size=1024 * 1024 * 10,
file_name="test.mp4",
width=1920,
height=1080,
duration=35,
),
reply_to_message_id=4,
)
set_meta_data(meta, message)
self.assertEqual(meta.message_id, 5)
self.assertEqual(meta.message_date, datetime(2022, 8, 5, 14, 35, 12))
self.assertEqual(meta.message_caption, "#中文最吊 #哈啰")
self.assertEqual(meta.media_file_size, 1024 * 1024 * 10)
self.assertEqual(meta.media_width, 1920)
self.assertEqual(meta.media_height, 1080)
self.assertEqual(meta.media_file_name, "test.mp4")
self.assertEqual(meta.media_duration, 35)
download_filter.set_meta_data(meta)
download_filter.set_debug(True)
# test caption
self.assertEqual(filter_exec(download_filter, "caption == r'.*#test.*'"), False)
self.assertEqual(filter_exec(download_filter, "caption == r'.*#中文.*'"), True)
self.assertEqual(filter_exec(download_filter, "caption == r'.*#中文啊.*'"), False)
self.assertEqual(filter_exec(download_filter, "reply_to_message_id == 4"), True)
self.assertEqual(
filter_exec(download_filter, "reply_to_message_id != 4"), False
)
self.assertEqual(filter_exec(download_filter, "reply_to_message_id >= 4"), True)
def test_check_filter(self):
download_filter = Filter()
meta = MetaData()
message = MockMessage(
id=5,
media=True,
date=datetime(2022, 8, 5, 14, 35, 12),
chat_title="test2",
caption=None,
video=MockVideo(
mime_type="video/mp4",
file_size=1024 * 1024 * 10,
file_name="test.mp4",
width=1920,
height=1080,
duration=35,
),
)
set_meta_data(meta, message)
download_filter.set_debug(True)
download_filter.set_meta_data(meta)
# 1. ==
# 1.1 restring
self.assertEqual(
check_filter_exec(download_filter, "caption == rr'.*#中文啊.*'"),
(False, "Syntax error at '.*#中文啊.*'"),
)
self.assertEqual(
check_filter_exec(download_filter, "caption == r'.*#中文啊.*'"), (True, None)
)
self.assertEqual(
check_filter_exec(download_filter, "caption tis r'.*#中文啊.*'"),
(False, "Syntax error at 'tis'"),
)
# 1.2 string
self.assertEqual(
check_filter_exec(download_filter, "caption = '.*#中文啊.*'"), (True, None)
)
# 2. check type
# 2.1 str
self.assertEqual(
check_filter_exec(download_filter, "caption = 1"),
(False, "caption is str but 1 is not"),
)
self.assertEqual(
check_filter_exec(download_filter, "caption = 3KB"),
(False, "caption is str but 3072 is not"),
)
# 2.2 datetime
self.assertEqual(
check_filter_exec(download_filter, "message_date == '.*#中文啊.*'"),
(False, "2022-08-05 14:35:12 is datetime but .*#中文啊.* is not"),
)
# 2.3 int
self.assertEqual(
check_filter_exec(download_filter, "id == '.*'"),
(False, "5 is int but .* is not"),
)
self.assertEqual(
check_filter_exec(download_filter, "id == .*"),
(False, "Syntax error at '*'"),
)
self.assertEqual(
check_filter_exec(download_filter, "id == ."),
(False, "Syntax error at EOF"),
)
self.assertEqual(
check_filter_exec(download_filter, "id == ."),
(False, "Syntax error at EOF"),
)
# 2.3.1 custom token
self.assertEqual(
check_filter_exec(download_filter, "file_size == 3KB"), (True, None)
)
self.assertEqual(
check_filter_exec(download_filter, "file_size == 3kb"),
(False, "Syntax error at 'kb'"),
)
# 3. error name
self.assertEqual(
check_filter_exec(download_filter, "caption2 == .*#中文啊.*'"),
(False, "Undefined name caption2"),
)
# 4. datetime
self.assertEqual(
check_filter_exec(download_filter, "message_date == 2023/0b-05"),
(False, "Syntax error at 'b'"),
)
self.assertEqual(
check_filter_exec(download_filter, "message_date == 2023/01/45")[0], False
)
def test_normal(self):
download_filter = Filter()
print(download_filter.filter.names)
meta = MetaData(datetime(2022, 3, 8, 10, 0, 0), 0, "#高桥千x", 0, 0, 0, "", 0)
download_filter.set_meta_data(meta)
self.assertEqual(check_filter_exec(download_filter, "id > 1"), (True, None))
download_filter.set_debug(True)
filter_exec(download_filter, "caption == r'.*高桥.*'")
download_filter2 = Filter()
meta2 = MetaData(datetime(2022, 3, 8, 10, 0, 0), 0, "", 0, 0, 0, "", 0)
download_filter2.set_meta_data(meta2)
download_filter2.set_debug(True)
filter_exec(download_filter2, "caption == r'.*高桥.*'")
print(download_filter.filter.names)
download_filter.set_meta_data(meta)
self.assertEqual(check_filter_exec(download_filter, "id > 1"), (True, None))
download_filter.set_debug(True)
filter_exec(download_filter, "caption == r'.*高桥.*'")
filter_exec(download_filter, "caption == r'.*高桥.*'")
+255
View File
@@ -0,0 +1,255 @@
"""Unittest module for media downloader."""
import os
import sys
import unittest
from dataclasses import asdict
from unittest.mock import patch
from utils.format import (
Link,
create_progress_bar,
extract_info_from_link,
format_byte,
get_byte_from_str,
replace_date_time,
truncate_filename,
validate_title,
)
sys.path.append("..") # Adds higher directory to python modules path.
class FormatTestCase(unittest.TestCase):
def test_format_byte(self):
byte_list = [
"KB",
"MB",
"GB",
"TB",
"PB",
"EB",
"ZB",
"YB",
"BB",
"NB",
"DB",
"CB",
]
self.assertEqual(format_byte(0.1), "0.8b")
self.assertEqual(format_byte(1), "1B")
for i, value in enumerate(byte_list):
self.assertEqual(format_byte(pow(1024, i + 1)), "1.0" + value)
try:
format_byte(-1)
except Exception as e:
self.assertEqual(isinstance(e, ValueError), True)
def test_replace_date_time(self):
self.assertEqual(
replace_date_time(""),
"",
)
# split by '.'
self.assertEqual(
replace_date_time("xxxxx 2020.03.08 xxxxxxxxx"),
"xxxxx 2020-03-08 00:00:00 xxxxxxxxx",
)
# split by '-'
self.assertEqual(
replace_date_time("xxxxx 2020-03-08 xxxxxxxxxxxx"),
"xxxxx 2020-03-08 00:00:00 xxxxxxxxxxxx",
)
# split by '/'
self.assertEqual(
replace_date_time("xasd as 2020/03/08 21321fszv"),
"xasd as 2020-03-08 00:00:00 21321fszv",
)
# more different date
self.assertEqual(
replace_date_time("xxxxx 2020.03.08 2020.03.09 14:51 xxxxxxxxx"),
"xxxxx 2020-03-08 00:00:00 2020-03-09 14:51:00 xxxxxxxxx",
)
# more space
self.assertEqual(
replace_date_time("xxxxx 2020.03.08 2020.03.09 14:51 xxxxxxxxx"),
"xxxxx 2020-03-08 00:00:00 2020-03-09 14:51:00 xxxxxxxxx",
)
# more date format
self.assertEqual(
replace_date_time("xasd as 2020/03 21321fszv"),
"xasd as 2020-03-01 00:00:00 21321fszv",
)
self.assertEqual(
replace_date_time("xasd as 2020-03 21321fszv"),
"xasd as 2020-03-01 00:00:00 21321fszv",
)
self.assertEqual(
replace_date_time("xasd as 2020.03 21321fszv"),
"xasd as 2020-03-01 00:00:00 21321fszv",
)
def test_get_byte_from_str(self):
# B
self.assertEqual(get_byte_from_str("2B"), 2)
# KB
self.assertEqual(get_byte_from_str("2KB"), 2 * 1024)
self.assertEqual(get_byte_from_str("1024KB"), 1024 * 1024)
self.assertEqual(get_byte_from_str("2024KB"), 2024 * 1024)
self.assertEqual(get_byte_from_str("4000KB"), 4000 * 1024)
# MB
self.assertEqual(get_byte_from_str("2MB"), 2 * 1024 * 1024)
self.assertEqual(get_byte_from_str("1024MB"), 1024 * 1024 * 1024)
# GB
self.assertEqual(get_byte_from_str("2GB"), 2 * 1024 * 1024 * 1024)
# TB
self.assertEqual(get_byte_from_str("2TB"), 2 * 1024 * 1024 * 1024 * 1024)
self.assertEqual(get_byte_from_str("1024TB"), 1024 * 1024 * 1024 * 1024 * 1024)
# more str
self.assertEqual(get_byte_from_str("2BW"), 2)
self.assertEqual(get_byte_from_str("2WBW"), None)
self.assertEqual(get_byte_from_str("2CB"), None)
def test_extract_info_from_link(self):
test_cases = [
("https://t.me/", Link(group_id=None)),
("https://t.me/username/1234", Link(group_id="username", post_id=1234)),
("https://t.me/username", Link(group_id="username")),
("https://t.me/c/213213/91011", Link(group_id=-100213213, post_id=91011)),
(
"https://t.me/test123/1/1234",
Link(group_id="test123", topic_id=1, post_id=1234),
),
("me", Link(group_id="me")),
("self", Link(group_id="self")),
(
"https://t.me/opencfdchannel/4434?comment=360409",
Link(group_id="opencfdchannel", comment_id=360409),
),
("https://t.me/telegram/193", Link(group_id="telegram", post_id=193)),
(
"https://t.me/c/1697797156/151",
Link(group_id=-1001697797156, post_id=151),
),
(
"https://t.me/iFreeKnow/45662/55005",
Link(group_id="iFreeKnow", topic_id=45662, post_id=55005),
),
(
"https://t.me/c/1492447836/251015/251021",
Link(group_id=-1001492447836, topic_id=251015, post_id=251021),
),
]
for link, expected in test_cases:
result = extract_info_from_link(link)
self.assertEqual(asdict(result), asdict(expected))
def test_create_progress_bar(self):
progress = 50
progress_bar = create_progress_bar(progress)
self.assertEqual(progress_bar, "█████░░░░░")
def test_create_progress_bar_with_custom_bars(self):
progress = 75
total_bars = 20
progress_bar = create_progress_bar(progress, total_bars)
self.assertEqual(progress_bar, "███████████████░░░░░")
class TestTruncateFilename(unittest.TestCase):
def test_truncate_filename(self):
test_cases = [
("testfile.txt", 240, "testfile.txt"),
("testfile.txt", 5, "t.txt"),
("a" * 240 + ".txt", 240, "a" * 236 + ".txt"),
("a" * 241 + ".txt", 240, "a" * 236 + ".txt"),
]
for path, limit, expected in test_cases:
self.assertEqual(truncate_filename(path, limit), expected)
@unittest.skipIf(sys.platform.startswith("win"), "requires Unix-based system")
def test_linux_filename_too_long(self):
long_filename = "a" * 265 + ".txt"
with self.assertRaises(OSError):
with open(long_filename, "w") as f:
f.write("test")
long_filename = "a" * 265 + ".txt"
long_filename = truncate_filename(long_filename) + ".temp"
try:
with open(long_filename, "w") as f:
f.write("test")
os.remove(long_filename)
except Exception:
self.assertEqual(False, True)
@unittest.skipIf(not sys.platform.startswith("win"), "requires Windows system")
def test_windows_filename_too_long(self):
long_filename = "a" * 265 + ".txt"
with self.assertRaises(OSError):
with open(long_filename, "w") as f:
f.write("test")
long_filename = "a" * 265 + ".txt"
long_filename = truncate_filename(long_filename) + ".temp"
try:
with open(long_filename, "w") as f:
f.write("test")
os.remove(long_filename)
except Exception:
self.assertEqual(False, True)
@patch("builtins.open", unittest.mock.mock_open())
def test_file_creation(self):
file_name = "a" * 240 + ".txt"
truncated_file_name = truncate_filename(file_name)
with open(truncated_file_name, "w") as f:
f.write("test")
open.assert_called_once_with(truncated_file_name, "w")
class TestValidateTitle(unittest.TestCase):
def test_validate_title(self):
test_cases = [
("Hello, World!", "Hello, World!"),
("Invalid/Title", "Invalid_Title"),
("File\\Name", "File_Name"),
("Colons:Are:Not:Allowed", "Colons_Are_Not_Allowed"),
("Asterisks*In*Title", "Asterisks_In_Title"),
("Question?Mark", "Question_Mark"),
('Double"Quotes', "Double_Quotes"),
("Less<Than", "Less_Than"),
("Greater>Than", "Greater_Than"),
("Pipe|Symbol", "Pipe_Symbol"),
("Multi\nLine", "Multi_Line"),
]
for title, expected in test_cases:
with self.subTest(title=title, expected=expected):
self.assertEqual(validate_title(title), expected)
@patch("utils.format.re.sub")
def test_mock_re_sub(self, mock_re_sub):
title = "Invalid/Title"
mock_re_sub.return_value = "Mocked_Title"
result = validate_title(title)
self.assertEqual(result, "Mocked_Title")
mock_re_sub.assert_called_once_with(r"[/\\:*?\"<>|\n]", "_", title)
+30
View File
@@ -0,0 +1,30 @@
"""Unittest module for log handlers."""
import os
import sys
import unittest
import mock
sys.path.append("..") # Adds higher directory to python modules path.
from utils.log import LogFilter
class MockLog:
"""
Mock logs.
"""
def __init__(self, **kwargs):
self.funcName = kwargs["funcName"]
class MetaTestCase(unittest.TestCase):
def test_log_filter(self):
result = LogFilter().filter(MockLog(funcName="invoke"))
self.assertEqual(result, False)
result1 = LogFilter().filter(MockLog(funcName="get_file"))
self.assertEqual(result1, True)
result2 = LogFilter().filter(MockLog(funcName="Synced"))
self.assertEqual(result2, True)
+23
View File
@@ -0,0 +1,23 @@
"""Unittest module for media downloader."""
import os
import sys
import unittest
import mock
sys.path.append("..") # Adds higher directory to python modules path.
from utils.meta import print_meta
class MetaTestCase(unittest.TestCase):
@mock.patch("utils.meta.APP_VERSION", "test-version 1.0.0")
@mock.patch("utils.meta.DEVICE_MODEL", "CPython X.X.X")
@mock.patch("utils.meta.SYSTEM_VERSION", "System xx.x.xx")
@mock.patch("media_downloader.logger")
def test_print_meta(self, mock_logger):
print_meta(mock_logger)
calls = [
mock.call.info("Device: CPython X.X.X - test-version 1.0.0"),
mock.call.info("System: System xx.x.xx (EN)"),
]
mock_logger.assert_has_calls(calls, any_order=True)
+147
View File
@@ -0,0 +1,147 @@
"""Unittest module for update checker."""
import json
import sys
import unittest
import mock
sys.path.append("..") # Adds higher directory to python modules path.
from utils.updates import check_for_updates, get_latest_release
class FakeHTTPSConnection:
def __init__(self, status):
self.status = status
def request(self, *args, **kwargs):
pass
def getresponse(self):
return FakeHTTPSResponse(self.status)
class FakeHTTPSResponse:
def __init__(self, status):
self.status = status
def read(self):
if self.status == 200:
return b'{"name":"v0.0.0 2022-03-02","tag_name":"v0.0.0", "html_url":"https://github.com/tangyoha/telegram_media_downloader/releases/tag/v0.0.0"}'
else:
return b"{error}"
class MocResponse:
def __init__(self, text: str):
self.text = text
def new_request_get(*args, **kwargs):
return MocResponse('{"tag_name":"v0.0.0"}')
import unittest
from unittest.mock import MagicMock, patch
from utils import __version__
from utils.updates import check_for_updates, get_latest_release
class TestUpdates(unittest.TestCase):
@patch("requests.get")
def test_get_latest_release(self, mock_get):
# Mock the response from requests.get
mock_response = MagicMock()
mock_response.text = json.dumps(
{
"name": "v0.0.0 2022-03-02",
"tag_name": "v0.0.0",
"html_url": "https://github.com/tangyoha/telegram_media_downloader/releases/tag/v0.0.0",
}
)
mock_get.return_value = mock_response
# Call the function with a test proxy_config
proxy_config = {
"scheme": "http",
"hostname": "localhost",
"port": "8080",
"username": "user",
"password": "pass",
}
result = get_latest_release(proxy_config)
# Check the result
self.assertEqual(result["name"], "v0.0.0 2022-03-02")
self.assertEqual(result["tag_name"], "v0.0.0")
self.assertEqual(
result["html_url"],
"https://github.com/tangyoha/telegram_media_downloader/releases/tag/v0.0.0",
)
@patch("requests.get")
def test_get_latest_release_same_version(self, mock_get):
# Mock the response from requests.get
mock_response = MagicMock()
mock_response.text = json.dumps(
{
"name": f"v{__version__} 2022-03-02",
"tag_name": f"v{__version__}",
"html_url": "https://github.com/tangyoha/telegram_media_downloader/releases/tag/v0.0.0",
}
)
mock_get.return_value = mock_response
# Call the function with a test proxy_config
proxy_config = {
"scheme": "http",
"hostname": "localhost",
"port": "8080",
"username": "user",
"password": "pass",
}
result = get_latest_release(proxy_config)
# Check the result
self.assertEqual(result, {})
@patch("requests.get")
def test_get_latest_release_exception(self, mock_get):
# Mock the response from requests.get to raise an exception
mock_get.side_effect = Exception("Test exception")
# Call the function with a test proxy_config
proxy_config = {
"scheme": "http",
"hostname": "localhost",
"port": "8080",
"username": "user",
"password": "pass",
}
result = get_latest_release(proxy_config)
# Check the result
self.assertEqual(result, {})
@patch("utils.updates.get_latest_release")
@patch("utils.updates.Console")
def test_check_for_updates(self, mock_console, mock_get_latest_release):
# Mock the response from get_latest_release
mock_get_latest_release.return_value = {
"name": "v0.0.0 2022-03-02",
"tag_name": "v0.0.0",
"html_url": "https://github.com/tangyoha/telegram_media_downloader/releases/tag/v0.0.0",
}
# Call the function with a test proxy_config
proxy_config = {
"scheme": "http",
"hostname": "localhost",
"port": "8080",
"username": "user",
"password": "pass",
}
check_for_updates(proxy_config)
# Check the console output
mock_console.return_value.print.assert_called_once()