AbhiCalls 2.9.8__py3-none-any.whl → 2026.2.2__py3-none-any.whl
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.
- AbhiCalls/Start.py +29 -0
- AbhiCalls/__init__.py +10 -0
- AbhiCalls/_engine/native.py +17 -1
- AbhiCalls/controller.py +22 -3
- AbhiCalls/player.py +2 -1
- AbhiCalls/plugins/__init__.py +1 -0
- AbhiCalls/plugins/base.py +93 -0
- {abhicalls-2.9.8.dist-info → abhicalls-2026.2.2.dist-info}/METADATA +1 -1
- abhicalls-2026.2.2.dist-info/RECORD +17 -0
- abhicalls-2.9.8.dist-info/RECORD +0 -14
- {abhicalls-2.9.8.dist-info → abhicalls-2026.2.2.dist-info}/WHEEL +0 -0
- {abhicalls-2.9.8.dist-info → abhicalls-2026.2.2.dist-info}/top_level.txt +0 -0
AbhiCalls/Start.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from colorama import init, Fore, Style
|
|
3
|
+
from AbhiCalls import __version__, __author__
|
|
4
|
+
|
|
5
|
+
init(autoreset=True)
|
|
6
|
+
|
|
7
|
+
def check_latest_version(pkg_name="AbhiCalls"):
|
|
8
|
+
try:
|
|
9
|
+
response = requests.get(f"https://pypi.org/pypi/{pkg_name}/json", timeout=3)
|
|
10
|
+
if response.status_code == 200:
|
|
11
|
+
return response.json()["info"]["version"]
|
|
12
|
+
except Exception:
|
|
13
|
+
return None
|
|
14
|
+
|
|
15
|
+
def print_startup_message():
|
|
16
|
+
print(Fore.GREEN + "✅ AbhiCalls started...\n")
|
|
17
|
+
|
|
18
|
+
print(Fore.CYAN + f"Version : {__version__}")
|
|
19
|
+
print(Fore.CYAN + f"Author : {__author__}")
|
|
20
|
+
print(Fore.CYAN + "License : Abhishek Special")
|
|
21
|
+
print(Fore.CYAN + "GitHub : https://github.com/YouTubeMusicAPI/AbhiCalls")
|
|
22
|
+
print(Fore.CYAN + "Telegram : https://t.me/WhyAbhishek")
|
|
23
|
+
|
|
24
|
+
latest = check_latest_version("AbhiCalls")
|
|
25
|
+
if latest and latest != __version__:
|
|
26
|
+
print(Fore.YELLOW + "\nUpdate Available!")
|
|
27
|
+
print(Fore.YELLOW + f"New AbhiCalls v{latest} is now available!")
|
|
28
|
+
else:
|
|
29
|
+
print(Fore.GREEN + "\nYou are using the latest version!")
|
AbhiCalls/__init__.py
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
from AbhiCalls.vc import VoiceEngine
|
|
2
2
|
from AbhiCalls.runtime import idle
|
|
3
3
|
from .player import Player
|
|
4
|
+
from .plugins import Plugin
|
|
4
5
|
|
|
5
6
|
__all__ = ["VoiceEngine", "idle"]
|
|
7
|
+
|
|
8
|
+
__version__ = "2026.2.2"
|
|
9
|
+
__author__ = "ABHISHEK THAKUR"
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from .Start import print_startup_message
|
|
13
|
+
print_startup_message()
|
|
14
|
+
except Exception:
|
|
15
|
+
pass
|
AbhiCalls/_engine/native.py
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
from pytgcalls import PyTgCalls, filters
|
|
2
|
-
from pytgcalls.types import MediaStream, AudioQuality, StreamEnded
|
|
2
|
+
from pytgcalls.types import MediaStream, AudioQuality, StreamEnded, ChatUpdate
|
|
3
|
+
|
|
3
4
|
|
|
4
5
|
class _NativeEngine:
|
|
5
6
|
def __init__(self, app):
|
|
6
7
|
self._core = PyTgCalls(app)
|
|
7
8
|
self.on_end = None
|
|
9
|
+
self.on_vc_closed = None
|
|
8
10
|
|
|
11
|
+
# 🔹 STREAM END
|
|
9
12
|
@self._core.on_update(filters.stream_end())
|
|
10
13
|
async def _ended(_, update: StreamEnded):
|
|
11
14
|
if self.on_end:
|
|
12
15
|
await self.on_end(update.chat_id)
|
|
13
16
|
|
|
17
|
+
# 🔹 VC CLOSED
|
|
18
|
+
@self._core.on_update(
|
|
19
|
+
filters.chat_update(ChatUpdate.Status.CLOSED_VOICE_CHAT)
|
|
20
|
+
)
|
|
21
|
+
async def _vc_closed(_, update):
|
|
22
|
+
chat_id = update.chat_id
|
|
23
|
+
|
|
24
|
+
if self.on_vc_closed:
|
|
25
|
+
try:
|
|
26
|
+
await self.on_vc_closed(chat_id)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
print("[NativeEngine] on_vc_closed error:", e)
|
|
29
|
+
|
|
14
30
|
async def start(self):
|
|
15
31
|
await self._core.start()
|
|
16
32
|
|
AbhiCalls/controller.py
CHANGED
|
@@ -7,7 +7,11 @@ class VoiceController:
|
|
|
7
7
|
def __init__(self, engine):
|
|
8
8
|
self.engine = engine
|
|
9
9
|
self.player = Player(engine)
|
|
10
|
+
|
|
11
|
+
# engine hooks
|
|
10
12
|
self.engine.on_end = self._on_end
|
|
13
|
+
self.engine.on_vc_closed = self._on_vc_closed
|
|
14
|
+
|
|
11
15
|
self.plugins = []
|
|
12
16
|
|
|
13
17
|
def load_plugin(self, plugin):
|
|
@@ -52,7 +56,7 @@ class VoiceController:
|
|
|
52
56
|
first_pos = pos
|
|
53
57
|
last_song = song
|
|
54
58
|
|
|
55
|
-
#
|
|
59
|
+
# first song actually started
|
|
56
60
|
if first_pos == 1 and last_song:
|
|
57
61
|
await self._hook("on_song_start", chat_id, last_song)
|
|
58
62
|
|
|
@@ -97,12 +101,10 @@ class VoiceController:
|
|
|
97
101
|
async def _on_end(self, chat_id):
|
|
98
102
|
q = self.player.queues.get(chat_id)
|
|
99
103
|
|
|
100
|
-
# old song end hook
|
|
101
104
|
old_song = q.current() if q else None
|
|
102
105
|
if old_song:
|
|
103
106
|
await self._hook("on_song_end", chat_id, old_song)
|
|
104
107
|
|
|
105
|
-
# move to next song
|
|
106
108
|
await self.player.skip(chat_id)
|
|
107
109
|
|
|
108
110
|
q = self.player.queues.get(chat_id)
|
|
@@ -110,3 +112,20 @@ class VoiceController:
|
|
|
110
112
|
|
|
111
113
|
if next_song:
|
|
112
114
|
await self._hook("on_song_start", chat_id, next_song)
|
|
115
|
+
|
|
116
|
+
# =========================
|
|
117
|
+
# VC CLOSED (CLEANUP)
|
|
118
|
+
# =========================
|
|
119
|
+
async def _on_vc_closed(self, chat_id):
|
|
120
|
+
q = self.player.queues.get(chat_id)
|
|
121
|
+
if q:
|
|
122
|
+
q.clear()
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
await self.player.stop(chat_id)
|
|
126
|
+
except:
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
await self._hook("on_vc_closed", chat_id)
|
|
130
|
+
print(f"[VoiceController] VC closed → cleaned {chat_id}")
|
|
131
|
+
|
AbhiCalls/player.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .base import Plugin
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
QUEUE_DELETE_AFTER = 30 # seconds
|
|
5
|
+
VC_END_DELETE_AFTER = 10 # seconds
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Plugin:
|
|
9
|
+
name = "base"
|
|
10
|
+
|
|
11
|
+
def __init__(self, app):
|
|
12
|
+
self.app = app
|
|
13
|
+
self.now_playing_msg = {} # chat_id -> message
|
|
14
|
+
|
|
15
|
+
async def on_song_start(self, chat_id, song):
|
|
16
|
+
caption = (
|
|
17
|
+
"▶️ Nᴏᴡ Pʟᴀʏɪɴɢ\n\n"
|
|
18
|
+
f"🎵 Tɪᴛʟᴇ : [{song.title[:19]}]({song.url})\n"
|
|
19
|
+
f"⏱ Dᴜʀᴀᴛɪᴏɴ : {song.duration}\n"
|
|
20
|
+
f"🙋 Rᴇǫᴜᴇsᴛᴇᴅ Bʏ : {song.requested_by}"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# delete old now-playing msg if exists
|
|
24
|
+
old = self.now_playing_msg.get(chat_id)
|
|
25
|
+
if old:
|
|
26
|
+
try:
|
|
27
|
+
await old.delete()
|
|
28
|
+
except:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
if song.thumb:
|
|
32
|
+
msg = await self.app.send_photo(
|
|
33
|
+
chat_id,
|
|
34
|
+
photo=song.thumb,
|
|
35
|
+
caption=caption
|
|
36
|
+
)
|
|
37
|
+
else:
|
|
38
|
+
msg = await self.app.send_message(chat_id, caption)
|
|
39
|
+
|
|
40
|
+
# store current now playing msg
|
|
41
|
+
self.now_playing_msg[chat_id] = msg
|
|
42
|
+
|
|
43
|
+
async def on_song_end(self, chat_id, song):
|
|
44
|
+
# delete current song msg when song ends
|
|
45
|
+
msg = self.now_playing_msg.pop(chat_id, None)
|
|
46
|
+
if msg:
|
|
47
|
+
try:
|
|
48
|
+
await msg.delete()
|
|
49
|
+
except:
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
async def on_queue_add(self, chat_id, song, position):
|
|
53
|
+
if position == 1:
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
caption = (
|
|
57
|
+
"➕ Aᴅᴅᴇᴅ Tᴏ Qᴜᴇᴜᴇ\n\n"
|
|
58
|
+
f"🎵 Tɪᴛʟᴇ : [{song.title[:19]}]({song.url})\n"
|
|
59
|
+
f"⏱ Dᴜʀᴀᴛɪᴏɴ : {song.duration}\n"
|
|
60
|
+
f"🙋 Rᴇǫᴜᴇsᴛᴇᴅ Bʏ : {song.requested_by}\n"
|
|
61
|
+
f"📍 Pᴏsɪᴛɪᴏɴ : {position}"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if song.thumb:
|
|
65
|
+
msg = await self.app.send_photo(
|
|
66
|
+
chat_id,
|
|
67
|
+
photo=song.thumb,
|
|
68
|
+
caption=caption
|
|
69
|
+
)
|
|
70
|
+
else:
|
|
71
|
+
msg = await self.app.send_message(chat_id, caption)
|
|
72
|
+
|
|
73
|
+
# auto delete queue msg after 30 sec
|
|
74
|
+
asyncio.create_task(self._auto_delete(msg, QUEUE_DELETE_AFTER))
|
|
75
|
+
|
|
76
|
+
async def on_vc_closed(self, chat_id):
|
|
77
|
+
try:
|
|
78
|
+
msg = await self.app.send_message(
|
|
79
|
+
chat_id,
|
|
80
|
+
"🔴 Vᴏɪᴄᴇ Cʜᴀᴛ Eɴᴅᴇᴅ\n\n"
|
|
81
|
+
"🧹 Qᴜᴇᴜᴇ Cʟᴇᴀʀᴇᴅ & Pʟᴀʏᴇʀ Sᴛᴏᴘᴘᴇᴅ."
|
|
82
|
+
)
|
|
83
|
+
asyncio.create_task(self._auto_delete(msg, VC_END_DELETE_AFTER))
|
|
84
|
+
except:
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
async def _auto_delete(self, msg, delay):
|
|
88
|
+
try:
|
|
89
|
+
await asyncio.sleep(delay)
|
|
90
|
+
await msg.delete()
|
|
91
|
+
except:
|
|
92
|
+
pass
|
|
93
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
AbhiCalls/Start.py,sha256=Z4Kn3p8elM9Sgo3H_7EBP8dfHknsjgiaUaEs1GEqcnY,1068
|
|
2
|
+
AbhiCalls/__init__.py,sha256=qClYd7guH3WOXqKuTIpNWVS3PYZvNIy68k-UgrmkUSc,325
|
|
3
|
+
AbhiCalls/controller.py,sha256=5fBN8qIqiaCuIOsoLqh_rJz33_Zqtrf5nlm27mMD-hk,3685
|
|
4
|
+
AbhiCalls/models.py,sha256=fwMdHKE0z6qB98nHJ8E1uYU3JSk25LGxaaeAz1JkAH0,791
|
|
5
|
+
AbhiCalls/player.py,sha256=85_kitFEh7N65q9hWB6lnFRAz_ZpDctpGfTsA_-6m54,2285
|
|
6
|
+
AbhiCalls/queue.py,sha256=iRrTvt1rU-diarSBCfxjeY-4uJ97oUsvDqtPpbB4UQY,1212
|
|
7
|
+
AbhiCalls/runtime.py,sha256=4_WmHirGwNOyn1Iuzbhecb_ao7qMDh1erFzp0ZaLze0,966
|
|
8
|
+
AbhiCalls/vc.py,sha256=ld3C4-QNDrHBQPrNzIuNTcu7zk1pVOo9rvrQBUsTI8s,309
|
|
9
|
+
AbhiCalls/yt.py,sha256=h0QRNK9sy-5wIDueiy-uMUxruV7z5m3xjUyRPoFT6_s,2594
|
|
10
|
+
AbhiCalls/_engine/__init__.py,sha256=pTqDs11-vYr-wuwtd7h3EkspDquGu84jWfN54ajl0kM,34
|
|
11
|
+
AbhiCalls/_engine/native.py,sha256=7Lo8SFidlXzOUXl9OtPYDMKi6e81rX2G6Kt18gfSh0Q,1773
|
|
12
|
+
AbhiCalls/plugins/__init__.py,sha256=rSCdGAjFfrzz-XQIFRjOcl629mPCo17n77Fn9lxLcPI,25
|
|
13
|
+
AbhiCalls/plugins/base.py,sha256=sGw4bahjD89ct88x2khSNRefclHhLIAnumXdQ9BjmHw,2774
|
|
14
|
+
abhicalls-2026.2.2.dist-info/METADATA,sha256=U4UlbTyfGf86q5lZUZMJAGuRdWusz75QC23UPqEhtTE,1212
|
|
15
|
+
abhicalls-2026.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
16
|
+
abhicalls-2026.2.2.dist-info/top_level.txt,sha256=3_ZgJEaE0rS9jpmEMi6oIXEtMzIagrn70XtK7H6w2gA,10
|
|
17
|
+
abhicalls-2026.2.2.dist-info/RECORD,,
|
abhicalls-2.9.8.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
AbhiCalls/__init__.py,sha256=8Bgye84bSUJVFLhm2HPc2piO3YHZb67EihvJlGZxvDs,134
|
|
2
|
-
AbhiCalls/controller.py,sha256=KYppQPpWhTpWj-gwmZqyGgX5liZHAaWRIMqksZPzXzU,3241
|
|
3
|
-
AbhiCalls/models.py,sha256=fwMdHKE0z6qB98nHJ8E1uYU3JSk25LGxaaeAz1JkAH0,791
|
|
4
|
-
AbhiCalls/player.py,sha256=UlAWmhZqHFjtAplA9-6lXFkVAu4pyEWDGbF8Wj9KYkM,2286
|
|
5
|
-
AbhiCalls/queue.py,sha256=iRrTvt1rU-diarSBCfxjeY-4uJ97oUsvDqtPpbB4UQY,1212
|
|
6
|
-
AbhiCalls/runtime.py,sha256=4_WmHirGwNOyn1Iuzbhecb_ao7qMDh1erFzp0ZaLze0,966
|
|
7
|
-
AbhiCalls/vc.py,sha256=ld3C4-QNDrHBQPrNzIuNTcu7zk1pVOo9rvrQBUsTI8s,309
|
|
8
|
-
AbhiCalls/yt.py,sha256=h0QRNK9sy-5wIDueiy-uMUxruV7z5m3xjUyRPoFT6_s,2594
|
|
9
|
-
AbhiCalls/_engine/__init__.py,sha256=pTqDs11-vYr-wuwtd7h3EkspDquGu84jWfN54ajl0kM,34
|
|
10
|
-
AbhiCalls/_engine/native.py,sha256=KJajnL9urwrx0PaOEJj4-pGGnhz4X9FDI6rTGrbCLoI,1272
|
|
11
|
-
abhicalls-2.9.8.dist-info/METADATA,sha256=VzXnK3k_eeFbdczlR7RAFG8jmLrdA53aHFRUB1NQEvc,1209
|
|
12
|
-
abhicalls-2.9.8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
-
abhicalls-2.9.8.dist-info/top_level.txt,sha256=3_ZgJEaE0rS9jpmEMi6oIXEtMzIagrn70XtK7H6w2gA,10
|
|
14
|
-
abhicalls-2.9.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|