warp-beacon 2.1.10__tar.gz → 2.1.12__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 (54) hide show
  1. {warp_beacon-2.1.10/warp_beacon.egg-info → warp_beacon-2.1.12}/PKG-INFO +1 -1
  2. warp_beacon-2.1.12/warp_beacon/__version__.py +2 -0
  3. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/jobs/abstract.py +5 -1
  4. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scheduler/scheduler.py +2 -1
  5. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/__init__.py +0 -4
  6. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/account_selector.py +2 -0
  7. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/telegram/bot.py +56 -15
  8. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/telegram/handlers.py +14 -6
  9. {warp_beacon-2.1.10 → warp_beacon-2.1.12/warp_beacon.egg-info}/PKG-INFO +1 -1
  10. warp_beacon-2.1.10/warp_beacon/__version__.py +0 -2
  11. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/LICENSE +0 -0
  12. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/MANIFEST.in +0 -0
  13. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/README.md +0 -0
  14. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/assets/placeholder.gif +0 -0
  15. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/etc/.gitignore +0 -0
  16. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/etc/accounts.json +0 -0
  17. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/etc/warp_beacon.conf +0 -0
  18. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/etc/warp_beacon.service +0 -0
  19. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/pyproject.toml +0 -0
  20. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/setup.cfg +0 -0
  21. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/setup.py +0 -0
  22. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/__init__.py +0 -0
  23. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/compress/__init__.py +0 -0
  24. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/compress/video.py +0 -0
  25. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/jobs/__init__.py +0 -0
  26. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/jobs/download_job.py +0 -0
  27. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/jobs/types.py +0 -0
  28. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/jobs/upload_job.py +0 -0
  29. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/mediainfo/__init__.py +0 -0
  30. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/mediainfo/abstract.py +0 -0
  31. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/mediainfo/audio.py +0 -0
  32. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/mediainfo/silencer.py +0 -0
  33. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/mediainfo/video.py +0 -0
  34. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scheduler/__init__.py +0 -0
  35. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/abstract.py +0 -0
  36. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/exceptions.py +0 -0
  37. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/instagram/__init__.py +0 -0
  38. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/instagram/instagram.py +0 -0
  39. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/youtube/__init__.py +0 -0
  40. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/youtube/abstract.py +0 -0
  41. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/youtube/music.py +0 -0
  42. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/youtube/shorts.py +0 -0
  43. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/scraper/youtube/youtube.py +0 -0
  44. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/storage/__init__.py +0 -0
  45. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/telegram/__init__.py +0 -0
  46. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/telegram/placeholder_message.py +0 -0
  47. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/telegram/utils.py +0 -0
  48. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/uploader/__init__.py +0 -0
  49. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon/warp_beacon.py +0 -0
  50. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon.egg-info/SOURCES.txt +0 -0
  51. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon.egg-info/dependency_links.txt +0 -0
  52. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon.egg-info/entry_points.txt +0 -0
  53. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon.egg-info/requires.txt +0 -0
  54. {warp_beacon-2.1.10 → warp_beacon-2.1.12}/warp_beacon.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: warp_beacon
3
- Version: 2.1.10
3
+ Version: 2.1.12
4
4
  Summary: Telegram bot for expanding external media links
5
5
  Home-page: https://github.com/sb0y/warp_beacon
6
6
  Author: Andrey Bagrintsev
@@ -0,0 +1,2 @@
1
+ __version__ = "2.1.12"
2
+
@@ -1,9 +1,11 @@
1
1
  import os
2
- from abc import ABC, abstractmethod
2
+ from abc import ABC
3
3
  from typing import TypedDict
4
4
  from typing_extensions import Unpack
5
5
  import uuid
6
6
 
7
+ from pyrogram.enums import ChatType
8
+
7
9
  from warp_beacon.jobs import Origin
8
10
  from warp_beacon.jobs.types import JobType
9
11
 
@@ -37,6 +39,7 @@ class JobSettings(TypedDict):
37
39
  account_switches: int
38
40
  yt_auth: bool
39
41
  session_validation: bool
42
+ chat_type: ChatType
40
43
 
41
44
  class AbstractJob(ABC):
42
45
  job_id: uuid.UUID = None
@@ -68,6 +71,7 @@ class AbstractJob(ABC):
68
71
  account_switches: int = 0
69
72
  yt_auth: bool = False
70
73
  session_validation: bool = False
74
+ chat_type: ChatType = None
71
75
 
72
76
  def __init__(self, **kwargs: Unpack[JobSettings]) -> None:
73
77
  if kwargs:
@@ -11,7 +11,7 @@ class IGScheduler(object):
11
11
  thread = None
12
12
  event = None
13
13
 
14
- def __init__(self, downloader: "warp_beacon.scraper.AsyncDownloader") -> None:
14
+ def __init__(self, downloader: warp_beacon.scraper.AsyncDownloader) -> None:
15
15
  self.downloader = downloader
16
16
  self.event = threading.Event()
17
17
 
@@ -24,6 +24,7 @@ class IGScheduler(object):
24
24
 
25
25
  def stop(self) -> None:
26
26
  self.running = False
27
+ self.event.set()
27
28
  if self.thread:
28
29
  t_id = self.thread.native_id
29
30
  logging.info("Stopping scheduler thread #'%s'", t_id)
@@ -15,7 +15,6 @@ from warp_beacon.jobs.download_job import DownloadJob
15
15
  from warp_beacon.jobs.upload_job import UploadJob
16
16
  from warp_beacon.jobs.types import JobType
17
17
  from warp_beacon.scraper.account_selector import AccountSelector
18
- from warp_beacon.scheduler.scheduler import IGScheduler
19
18
 
20
19
  import logging
21
20
 
@@ -37,8 +36,6 @@ class AsyncDownloader(object):
37
36
  self.uploader = uploader
38
37
  self.workers_count = workers_count
39
38
  self.acc_selector = AccountSelector(ACC_FILE)
40
- self.scheduler = IGScheduler(self)
41
- self.scheduler.start()
42
39
 
43
40
  def __del__(self) -> None:
44
41
  self.stop_all()
@@ -329,7 +326,6 @@ class AsyncDownloader(object):
329
326
 
330
327
  def stop_all(self) -> None:
331
328
  self.allow_loop.value = 0
332
- self.scheduler.stop()
333
329
  for proc in self.workers:
334
330
  if proc.is_alive():
335
331
  logging.info("stopping process #%d", proc.pid)
@@ -80,4 +80,6 @@ class AccountSelector(object):
80
80
 
81
81
  def count_service_accounts(self, mod_name: Origin) -> int:
82
82
  module_name = 'youtube' if next((s for s in ("yt", "youtube", "youtu_be") if s in mod_name.value), None) else 'instagram'
83
+ if module_name not in self.accounts_meta_data:
84
+ return 0
83
85
  return len(self.accounts_meta_data[module_name])
@@ -4,7 +4,7 @@ import signal
4
4
  import uvloop
5
5
 
6
6
  from pyrogram import Client, filters
7
- from pyrogram.enums import ParseMode
7
+ from pyrogram.enums import ParseMode, ChatType
8
8
  from pyrogram.handlers import MessageHandler, CallbackQueryHandler
9
9
  from pyrogram.types import Message, InputMedia, InputMediaAudio, InputMediaPhoto, InputMediaVideo, InputMediaAnimation, InputMediaDocument, InlineKeyboardButton, InlineKeyboardMarkup
10
10
  from pyrogram.errors import RPCError, FloodWait, NetworkMigrate, BadRequest, MultiMediaTooLong, MessageIdInvalid
@@ -18,6 +18,7 @@ from warp_beacon.uploader import AsyncUploader
18
18
  from warp_beacon.jobs.upload_job import UploadJob
19
19
  from warp_beacon.jobs.types import JobType
20
20
  from warp_beacon.telegram.utils import Utils
21
+ from warp_beacon.scheduler.scheduler import IGScheduler
21
22
 
22
23
  import logging
23
24
 
@@ -29,6 +30,7 @@ class Bot(object):
29
30
  client = None
30
31
  handlers = None
31
32
  placeholder = None
33
+ scheduler = None
32
34
 
33
35
  def __init__(self, tg_bot_name: str, tg_token: str, tg_api_id: str, tg_api_hash: str) -> None:
34
36
  # Enable logging
@@ -70,8 +72,11 @@ class Bot(object):
70
72
  uploader=self.uploader
71
73
  )
72
74
 
75
+ self.scheduler = IGScheduler(self.downloader)
76
+
73
77
  self.downloader.start()
74
78
  self.uploader.start()
79
+ self.scheduler.start()
75
80
 
76
81
  self.handlers = Handlers(self)
77
82
 
@@ -94,9 +99,9 @@ class Bot(object):
94
99
 
95
100
  def stop(self) -> None:
96
101
  logging.info("Warp Beacon terminating. This may take a while ...")
102
+ self.scheduler.stop()
97
103
  self.downloader.stop_all()
98
104
  self.uploader.stop_all()
99
- #self.client.stop()
100
105
 
101
106
  async def send_text(self, chat_id: int, text: str, reply_id: int = None) -> int:
102
107
  try:
@@ -141,12 +146,28 @@ class Bot(object):
141
146
 
142
147
  return []
143
148
 
149
+ def build_signature_caption(self, job: UploadJob) -> str:
150
+ caption = ""
151
+ if job.chat_type in (ChatType.GROUP, ChatType.SUPERGROUP):
152
+ if job.source_usename:
153
+ caption += f"Requested by **@{job.source_usename}**"
154
+ if job.source_usename and job.url:
155
+ caption += " | "
156
+ if job.url:
157
+ caption += f"[Source link]({job.url})"
158
+
159
+ return caption
160
+
144
161
  def build_tg_args(self, job: UploadJob) -> dict:
145
162
  args = {}
146
163
  if job.media_type == JobType.VIDEO:
147
164
  if job.tg_file_id:
148
165
  if job.placeholder_message_id:
149
- args["media"] = InputMediaVideo(media=job.tg_file_id.replace(":video", ''), supports_streaming=True)
166
+ args["media"] = InputMediaVideo(
167
+ media=job.tg_file_id.replace(":video", ''),
168
+ supports_streaming=True,
169
+ caption=self.build_signature_caption(job)
170
+ )
150
171
  else:
151
172
  args["video"] = job.tg_file_id.replace(":video", '')
152
173
  else:
@@ -157,7 +178,8 @@ class Bot(object):
157
178
  width=job.media_info["width"],
158
179
  height=job.media_info["height"],
159
180
  duration=round(job.media_info["duration"]),
160
- thumb=job.media_info["thumb"]
181
+ thumb=job.media_info["thumb"],
182
+ caption=self.build_signature_caption(job)
161
183
  )
162
184
  else:
163
185
  args["video"] = job.local_media_path
@@ -166,18 +188,23 @@ class Bot(object):
166
188
  args["height"] = job.media_info["height"]
167
189
  args["duration"] = round(job.media_info["duration"])
168
190
  args["thumb"] = job.media_info["thumb"]
191
+ args["caption"] = self.build_signature_caption(job)
169
192
 
170
193
  args["file_name"] = "downloaded_via_warp_beacon_bot%s" % (os.path.splitext(job.local_media_path)[-1])
171
194
  elif job.media_type == JobType.IMAGE:
172
195
  if job.tg_file_id:
173
196
  if job.placeholder_message_id:
174
- args["media"] = InputMediaPhoto(media=job.tg_file_id.replace(":image", ''))
197
+ args["media"] = InputMediaPhoto(
198
+ media=job.tg_file_id.replace(":image", ''),
199
+ caption=self.build_signature_caption(job)
200
+ )
175
201
  else:
176
202
  args["photo"] = job.tg_file_id.replace(":image", '')
177
203
  else:
178
204
  if job.placeholder_message_id:
179
205
  args["media"] = InputMediaPhoto(
180
- media=job.local_media_path
206
+ media=job.local_media_path,
207
+ caption=self.build_signature_caption(job)
181
208
  )
182
209
  else:
183
210
  args["photo"] = job.local_media_path
@@ -185,7 +212,8 @@ class Bot(object):
185
212
  if job.tg_file_id:
186
213
  if job.placeholder_message_id:
187
214
  args["media"] = InputMediaAudio(
188
- media=job.tg_file_id.replace(":audio", '')
215
+ media=job.tg_file_id.replace(":audio", ''),
216
+ caption=self.build_signature_caption(job)
189
217
  )
190
218
  else:
191
219
  args["audio"] = job.tg_file_id.replace(":audio", '')
@@ -197,6 +225,7 @@ class Bot(object):
197
225
  thumb=job.media_info["thumb"],
198
226
  duration=round(job.media_info["duration"]),
199
227
  title=job.canonical_name,
228
+ caption=self.build_signature_caption(job)
200
229
  )
201
230
  else:
202
231
  args["audio"] = job.local_media_path
@@ -204,6 +233,7 @@ class Bot(object):
204
233
  args["thumb"] = job.media_info["thumb"]
205
234
  args["duration"] = round(job.media_info["duration"])
206
235
  args["title"] = job.canonical_name
236
+ args["caption"] = self.build_signature_caption(job)
207
237
  #args["file_name"] = "%s%s" % (job.canonical_name, os.path.splitext(job.local_media_path)[-1]),
208
238
  elif job.media_type == JobType.ANIMATION:
209
239
  if job.tg_file_id:
@@ -220,7 +250,8 @@ class Bot(object):
220
250
  thumb=job.media_info["thumb"],
221
251
  duration=round(job.media_info["duration"]),
222
252
  width=job.media_info["width"],
223
- height=job.media_info["height"]
253
+ height=job.media_info["height"],
254
+ caption=self.build_signature_caption(job)
224
255
  )
225
256
  else:
226
257
  args["animation"] = job.local_media_path
@@ -228,6 +259,7 @@ class Bot(object):
228
259
  args["height"] = job.media_info["height"]
229
260
  args["duration"] = round(job.media_info["duration"])
230
261
  args["thumb"] = job.media_info["thumb"]
262
+ args["caption"] = self.build_signature_caption(job)
231
263
  elif job.media_type == JobType.COLLECTION:
232
264
  if job.tg_file_id:
233
265
  args["media"] = []
@@ -238,11 +270,11 @@ class Bot(object):
238
270
  ctype = JobType[mtype.upper()]
239
271
  ptr = None
240
272
  if ctype == JobType.VIDEO:
241
- ptr = InputMediaVideo(media=tg_id)
273
+ ptr = InputMediaVideo(media=tg_id, caption=self.build_signature_caption(job))
242
274
  elif ctype == JobType.IMAGE:
243
- ptr = InputMediaPhoto(media=tg_id)
275
+ ptr = InputMediaPhoto(media=tg_id, caption=self.build_signature_caption(job))
244
276
  elif ctype == JobType.ANIMATION:
245
- ptr = InputMediaAnimation(media=tg_id)
277
+ ptr = InputMediaAnimation(media=tg_id, caption=self.build_signature_caption(job))
246
278
  tg_chunk.append(ptr)
247
279
 
248
280
  args["media"].append(tg_chunk)
@@ -259,11 +291,13 @@ class Bot(object):
259
291
  height=j.media_info["height"],
260
292
  duration=round(j.media_info["duration"]),
261
293
  thumb=j.media_info["thumb"],
294
+ caption=self.build_signature_caption(job)
262
295
  )
263
296
  tg_chunk.append(vid)
264
297
  elif j.media_type == JobType.IMAGE:
265
298
  photo = InputMediaPhoto(
266
- media=j.local_media_path
299
+ media=j.local_media_path,
300
+ caption=self.build_signature_caption(job)
267
301
  )
268
302
  tg_chunk.append(photo)
269
303
  mediafs.append(tg_chunk)
@@ -329,11 +363,11 @@ class Bot(object):
329
363
  messages = await self.client.send_media_group(
330
364
  chat_id=job.chat_id,
331
365
  reply_to_message_id=job.message_id,
332
- media=media_chunk,
366
+ media=media_chunk
333
367
  )
334
368
  sent_messages += messages
335
369
  if job.media_collection:
336
- for j, chunk in enumerate(media_chunk):
370
+ for j, _ in enumerate(media_chunk):
337
371
  tg_file_id = Utils.extract_file_id(messages[j])
338
372
  if tg_file_id:
339
373
  job.media_collection[i][j].tg_file_id = tg_file_id
@@ -360,7 +394,7 @@ class Bot(object):
360
394
  if retry_amount+1 >= max_retries:
361
395
  msg = ""
362
396
  if hasattr(e, "MESSAGE") and e.MESSAGE:
363
- msg = "Telegram error: %s" % str(e.MESSAGE)
397
+ msg = f"Telegram error: {str(e.MESSAGE)}"
364
398
  else:
365
399
  msg = (f"Unknown Telegram error. Known information:\n```python\n{traceback.format_exc().strip()}```"
366
400
  "\nPlease [create issue](https://github.com/sb0y/warp_beacon/issues) with this info and service logs.")
@@ -374,4 +408,11 @@ class Bot(object):
374
408
  finally:
375
409
  job.remove_files()
376
410
 
411
+ if job.chat_type in (ChatType.GROUP, ChatType.SUPERGROUP):
412
+ try:
413
+ await self.client.delete_messages(job.chat_id, (job.message_id,))
414
+ except Exception as e:
415
+ logging.warning("Failed to delete source message. Check bot permissions in Telegram chat settings.")
416
+ logging.exception(e)
417
+
377
418
  return tg_file_ids
@@ -1,7 +1,7 @@
1
1
  from pyrogram import Client
2
2
  from pyrogram.types import Message, CallbackQuery
3
3
  from pyrogram.enums import ChatType, ParseMode
4
- from pyrogram.types import Chat, BotCommand
4
+ from pyrogram.types import BotCommand
5
5
 
6
6
  from urlextract import URLExtract
7
7
 
@@ -37,7 +37,9 @@ class Handlers(object):
37
37
  tg_file_id=d["tg_file_id"],
38
38
  chat_id=message.chat.id,
39
39
  media_type=JobType[d["media_type"].upper()],
40
- message_id=message.id
40
+ message_id=message.id,
41
+ chat_type=message.chat.type,
42
+ source_username=message.from_user
41
43
  )
42
44
  )
43
45
 
@@ -96,7 +98,9 @@ class Handlers(object):
96
98
  tg_file_id=",".join(tg_file_ids),
97
99
  message_id=effective_message_id,
98
100
  media_type=JobType.COLLECTION,
99
- chat_id=chat.id
101
+ chat_id=chat.id,
102
+ chat_type=message.chat.type,
103
+ source_username=message.from_user
100
104
  )
101
105
  )
102
106
  elif ent_len:
@@ -107,7 +111,9 @@ class Handlers(object):
107
111
  tg_file_id=tg_file_ids.pop(),
108
112
  message_id=effective_message_id,
109
113
  media_type=media_type,
110
- chat_id=chat.id
114
+ chat_id=chat.id,
115
+ chat_type=message.chat.type,
116
+ source_username=message.from_user
111
117
  )
112
118
  )
113
119
  else:
@@ -141,7 +147,7 @@ class Handlers(object):
141
147
  if not placeholder_message_id:
142
148
  await self.bot.send_text(
143
149
  chat_id=chat.id,
144
- reply_id=effective_message_id,
150
+ reply_id=effective_message_id,
145
151
  text="Failed to create message placeholder. Please check your bot Internet connection.")
146
152
  return
147
153
 
@@ -157,7 +163,9 @@ class Handlers(object):
157
163
  chat_id=chat.id,
158
164
  in_process=self.bot.uploader.is_inprocess(uniq_id),
159
165
  uniq_id=uniq_id,
160
- job_origin=origin
166
+ job_origin=origin,
167
+ source_username=message.from_user,
168
+ chat_type=chat.type
161
169
  ))
162
170
  self.bot.uploader.set_inprocess(uniq_id)
163
171
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: warp_beacon
3
- Version: 2.1.10
3
+ Version: 2.1.12
4
4
  Summary: Telegram bot for expanding external media links
5
5
  Home-page: https://github.com/sb0y/warp_beacon
6
6
  Author: Andrey Bagrintsev
@@ -1,2 +0,0 @@
1
- __version__ = "2.1.10"
2
-
File without changes
File without changes
File without changes
File without changes
File without changes