aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/settings.json2
-rw-r--r--video2story/__main__.py73
-rw-r--r--video2story/uploader.py125
3 files changed, 176 insertions, 24 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a205f43..d6063cb 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,5 @@
3 "**/__pycache__": true, 3 "**/__pycache__": true,
4 "**/.venv": true 4 "**/.venv": true
5 }, 5 },
6 "cSpell.words": ["screenshotting"] 6 "cSpell.words": ["screenshotting", "tdlib"]
7} 7}
diff --git a/video2story/__main__.py b/video2story/__main__.py
index 8e08cac..43c94b8 100644
--- a/video2story/__main__.py
+++ b/video2story/__main__.py
@@ -40,8 +40,7 @@ video_parser.add_argument(
40 default=60, 40 default=60,
41 help=( 41 help=(
42 "Specifies each story duration.\n" 42 "Specifies each story duration.\n"
43 "When set to 0 each story will be an image.\n" 43 "Max value is 60 and min value is 1.\n"
44 "Max value is 60 and min value is 0.\n"
45 "Default is 60." 44 "Default is 60."
46 ), 45 ),
47) 46)
@@ -67,7 +66,6 @@ video_parser.add_argument(
67 help="Specifies the second of the video from which processing will end.", 66 help="Specifies the second of the video from which processing will end.",
68) 67)
69 68
70
71story_parser = subparsers.add_parser( 69story_parser = subparsers.add_parser(
72 "story", 70 "story",
73 help="Story publishing module", 71 help="Story publishing module",
@@ -75,27 +73,31 @@ story_parser = subparsers.add_parser(
75) 73)
76 74
77story_parser.add_argument( 75story_parser.add_argument(
78 "action", 76 "phone",
79 type=str, 77 type=str,
80 metavar="ACTION", 78 metavar="PHONE",
81 choices=["publish-all", "publish-one"], 79 help="Your phone number.",
82 help=( 80)
83 "Specifies the type of publishing action.\n" 81story_parser.add_argument(
84 "Accept values: `publish-all` and `publish-one`.\n" 82 "input",
85 ), 83 type=str,
84 metavar="PATH",
85 help="Input folder with processed videos",
86) 86)
87story_parser.add_argument( 87story_parser.add_argument(
88 "privacy", 88 "-p",
89 "--privacy",
89 type=str, 90 type=str,
90 metavar="PRIVACY-MODE", 91 metavar="PRIVACY-MODE",
91 choices=["everyone", "contacts", "selected-users", "close-friends"], 92 choices=["everyone", "contacts", "selected", "friends"],
93 default="everyone",
92 help=( 94 help=(
93 "Specifies who can see you story.\n" 95 "Specifies who can see you story.\n"
94 "Accept values: `everyone`, `contacts`, `selected-users` and `close-friends`.\n" 96 "Accept values: `everyone`, `contacts`, `selected` and `friends`.\n"
95 "\n" 97 "\n"
96 "If set to `everyone` or `contacts`, the --user flag excludes the user who can see your story.\n" 98 "If set to `everyone` or `contacts`, the --user flag excludes the user who can see your story.\n"
97 "If set to `selected-users`, the --user flag specifies the user who can see your story.\n" 99 "If set to `selected`, the --user flag specifies the user who can see your story.\n"
98 "If set to `close-friends`, the --user flag will have no effect.\n" 100 "If set to `friends`, the --user flag will have no effect.\n"
99 ), 101 ),
100) 102)
101story_parser.add_argument( 103story_parser.add_argument(
@@ -104,7 +106,10 @@ story_parser.add_argument(
104 type=str, 106 type=str,
105 metavar="USERS", 107 metavar="USERS",
106 nargs="+", 108 nargs="+",
107 help="Behavior depends on privacy mode. See `privacy` description.", 109 help=(
110 "Behavior depends on privacy mode. See `privacy` description.\n"
111 "You can specify a username or user id."
112 ),
108) 113)
109story_parser.add_argument( 114story_parser.add_argument(
110 "-a", 115 "-a",
@@ -120,13 +125,24 @@ story_parser.add_argument(
120 ), 125 ),
121) 126)
122story_parser.add_argument( 127story_parser.add_argument(
128 "--save-to-profile",
129 action="store_true",
130 help="Keep the story accessible after expiration.",
131)
132story_parser.add_argument(
123 "--protected-content", 133 "--protected-content",
124 action="store_true", 134 action="store_true",
125 help="Protect story from forwarding and screenshotting.", 135 help="Protect story from forwarding and screenshotting.",
126) 136)
127story_parser.add_argument( 137story_parser.add_argument(
128 "-f", 138 "--tdlib",
129 "--from", 139 type=str,
140 metavar="PATH",
141 help="Path to tdlib library file.",
142)
143story_parser.add_argument(
144 "-s",
145 "--start",
130 type=int, 146 type=int,
131 metavar="VIDEO-ID", 147 metavar="VIDEO-ID",
132 default=0, 148 default=0,
@@ -137,8 +153,8 @@ story_parser.add_argument(
137 ), 153 ),
138) 154)
139story_parser.add_argument( 155story_parser.add_argument(
140 "-t", 156 "-e",
141 "--to", 157 "--end",
142 type=int, 158 type=int,
143 metavar="VIDEO-ID", 159 metavar="VIDEO-ID",
144 default=None, 160 default=None,
@@ -151,6 +167,10 @@ story_parser.add_argument(
151 167
152args = parser.parse_args() 168args = parser.parse_args()
153if args.module == "video": 169if args.module == "video":
170 if not (1 <= args.duration <= 60):
171 print("Duration must be between 1 and 60")
172 exit(1)
173
154 cut( 174 cut(
155 normpath(args.filename), 175 normpath(args.filename),
156 normpath(args.output), 176 normpath(args.output),
@@ -160,4 +180,15 @@ if args.module == "video":
160 args.end, 180 args.end,
161 ) 181 )
162elif args.module == "story": 182elif args.module == "story":
163 pass 183 upload(
184 args.phone,
185 normpath(args.input),
186 args.privacy,
187 args.users,
188 args.active_period,
189 args.save_to_profile,
190 args.protected_content,
191 args.tdlib,
192 args.start,
193 args.end,
194 )
diff --git a/video2story/uploader.py b/video2story/uploader.py
index dde8c98..d61ca43 100644
--- a/video2story/uploader.py
+++ b/video2story/uploader.py
@@ -1,2 +1,123 @@
1def upload() -> None: 1from os import listdir
2 pass \ No newline at end of file 2from os.path import isdir, join
3from threading import Event
4from time import sleep
5
6from telegram.client import Telegram
7
8
9def upload(
10 phone: str,
11 input_dir: str,
12 privacy: str,
13 users: list[str] | None,
14 active_period: str,
15 save_to_profile: bool,
16 protected_content: bool,
17 tdlib: str | None,
18 start: int,
19 end: int | None,
20) -> None:
21 telegram = Telegram(
22 api_id=2092395,
23 api_hash="38e26914cf0fda6356fda8f9d28f3bb9",
24 database_encryption_key="just a secret",
25 tdlib_verbosity=0,
26 library_path=tdlib,
27 phone=phone,
28 )
29 telegram.login()
30 me = int(telegram.call_method("getMe", block=True).update["id"])
31
32 if users is not None:
33 user_ids = []
34 for u in users:
35 if u.isdigit():
36 user_ids.append(int(u))
37 continue
38
39 try:
40 user_ids.append(
41 telegram.call_method(
42 "searchPublicChat",
43 {"username": u.strip().removeprefix("@")},
44 block=True,
45 ).update["id"]
46 )
47 except Exception:
48 print(f"An error occurred while getting user id ({u}).")
49 else:
50 user_ids = None
51
52 if not isdir(input_dir):
53 print("Input folder does not exists")
54 exit(1)
55
56 queue = set()
57 done = Event()
58
59 for i in range(start, (end + 1) if end is not None else len(listdir(input_dir))):
60 print(f"Adding to the uploading queue. (VIDEO-ID: {i})")
61
62 queue.add(
63 telegram.call_method(
64 "sendStory",
65 {
66 "chat_id": me,
67 "content": {
68 "@type": "inputStoryContentVideo",
69 "video": {
70 "@type": "inputFileLocal",
71 "path": join(input_dir, f"{i}.mp4"),
72 },
73 },
74 "areas": None,
75 "caption": None,
76 "privacy_settings": {
77 "everyone": {
78 "@type": "storyPrivacySettingsEveryone",
79 "except_user_ids": user_ids,
80 },
81 "contacts": {
82 "@type": "storyPrivacySettingsContacts",
83 "except_user_ids": user_ids,
84 },
85 "selected": {
86 "@type": "storyPrivacySettingsSelectedUsers",
87 "user_ids": user_ids,
88 },
89 "friends": {
90 "@type": "storyPrivacySettingsCloseFriends",
91 },
92 }[privacy],
93 "active_period": {
94 "6h": 21600,
95 "12h": 43200,
96 "24h": 86400,
97 "48h": 172800,
98 }[active_period],
99 "is_posted_to_chat_page": save_to_profile,
100 "protect_content": protected_content,
101 },
102 block=True,
103 ).update["content"]["video"]["video"]["id"]
104 )
105 sleep(0.5)
106
107 print(f"Uploading. {len(queue)} left")
108
109 def update(file: dict[str, object]) -> None:
110 if (
111 file["file"]["id"] in queue
112 and not file["file"]["remote"]["is_uploading_active"]
113 ):
114 queue.remove(file["file"]["id"])
115
116 if len(queue) == 0:
117 print("Done")
118 done.set()
119 else:
120 print(f"Uploading. {len(queue)} left")
121
122 telegram.add_update_handler("updateFile", update)
123 done.wait()