This repository has been archived by the owner on Feb 3, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 64
/
chat_vote.py
executable file
·177 lines (130 loc) · 7.7 KB
/
chat_vote.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
from handler.base_plugin import CommandPlugin
from utils import parse_user_id
from utils import plural_form
import asyncio, re
# Requirements:
# ChatMetaPlugin
# StoragePlugin
class VoterPlugin(CommandPlugin):
__slots__ = ("command_groups", "votes")
def __init__(self, vote_commands=None, vote_undo_commands=None,
votekick_commands=None, prefixes=None, strict=False):
"""This plugin allows users to do votes in chats with ability to kick someone with votekick"""
if not vote_commands:
vote_commands = ("vote", "+")
if not vote_undo_commands:
vote_undo_commands = ("unvote", "-")
if not votekick_commands:
votekick_commands = ("votekick", "выгоняем")
super().__init__(*(vote_commands + votekick_commands + vote_undo_commands), prefixes=prefixes, strict=strict)
self.command_groups = vote_commands, vote_undo_commands, votekick_commands
self.votes = {}
p = self.prefixes[-1]
self.description = [
f"Голосование",
f"Устраивайте голосование или выкидывайте людей из чата голосованием ;)",
f"{p}{vote_commands[0]} - голосовать за.",
f"{p}{vote_undo_commands[0]} - отменить свой голос.",
f"{p}{votekick_commands[0]} [кого кикать] - начать голосование за изгнание.",
f"{p}{vote_commands[0]} (нужно голосов, длительность голосования в секундах) тема голосования - начать голосование.",
f"Примеры:",
f"{p}{vote_commands[0]} (4, 30) Тут тема - начать голосование с темой \"Тут тема\", которое будет длиться 30 секунд и для положительного результата необходимо набрать 4 голоса.",
f"{p}{vote_commands[0]} Тут тема - начать голосование с темой \"Тут тема\", которое будет длиться 180 секунд и для положительного результата необходимо набрать 6, 8, 10 или все голоса (в зависимость от численности чата).",
]
async def do_vote(self, msg, title, maximum=None, votetime=180, kick=None):
unvoters = 2 if kick else 1
maximum = min(len(msg.meta["data_chat"]["chat_info"]["users"]) - \
unvoters, maximum if maximum else float("inf"))
await msg.answer(
f"Начало голосования с темой \"{title}\". Максимальное кол-во проголосовавших: {maximum}. "
f"Время голосования: {round(votetime/60, 2)} мин. Голосовать - {self.prefixes[-1]}{self.command_groups[0][0]}"
)
async def tick(timeleft):
await msg.answer(f"До конца голосования {plural_form(timeleft, ('секунда', 'секунды', 'секунд'))} ({len(self.votes[msg.chat_id])}/{maximum}).")
if votetime == 180:
times = [60, 60, 30, 15, 10, 5]
else:
times = []
temp = votetime
while temp > 0:
step = min(60, temp // 2)
while step % 5 != 0 and step < temp:
step += 1
times.append(step)
temp -= step
await tick(votetime)
for delta in times:
await asyncio.sleep(delta)
votetime -= delta
if votetime > 0: await tick(votetime)
result = len(self.votes[msg.chat_id])
if result >= maximum:
text = f"Голосование закончено c положительным результатом"
else:
text = "Голосование закончено с негативным результатом"
text += f" ({result}/{maximum})!"
await msg.answer(text)
if kick and result >= maximum:
await self.api.messages.removeChatUser(chat_id=msg.chat_id, user_id=kick)
del self.votes[msg.chat_id]
async def process_message(self, msg):
if msg.chat_id == 0:
return await msg.answer("Эта команда доступна только в беседах.")
if not msg.meta.get("data_chat", {}).get("chat_info"):
raise ValueError("This plugin requires `ChatMetaPlugin`.")
command, text = self.parse_message(msg, True)
if command in self.command_groups[0]:
if msg.chat_id not in self.votes:
if text:
match = re.match(r"\((\d+?)(, ?\d+?)?\)", text)
if match:
maximum = int(match.group(1)) if match.group(1) else None
votetime = int(match.group(2)[1:].strip()) if match.group(2) else 180
title = text[match.end():].strip()
else:
maximum = None
votetime = 180
title = text.strip()
self.votes[msg.chat_id] = set()
return asyncio.ensure_future(self.do_vote(msg, title, maximum=maximum, votetime=votetime))
return await msg.answer("Голосований не идёт в данный момент.")
if text:
return await msg.answer("Голосование уже идёт. Подождите его завершения.")
if msg.user_id in self.votes[msg.chat_id]:
return await msg.answer("Вы уже голосовали.")
self.votes[msg.chat_id].add(msg.user_id)
return await msg.answer("ОК+")
if command in self.command_groups[1]:
if msg.chat_id not in self.votes:
return await msg.answer("Голосований не идёт в данный момент.")
if msg.user_id not in self.votes[msg.chat_id]:
return await msg.answer("Вы не голосовали.")
self.votes[msg.chat_id].remove(msg.user_id)
return await msg.answer("ОК-")
if command in self.command_groups[2]:
if msg.chat_id in self.votes:
return await msg.answer("Голосование уже идёт. Подождите его завершения.")
puid = await parse_user_id(msg)
if not puid:
return await msg.answer(
"Введите пользователя, которого хотите выкинуть голосованием.\nПример: " +
self.prefixes[-1] + self.command_groups[2][0] + " 87641997"
)
user = None
for u in msg.meta["data_chat"]["chat_info"]["users"]:
if u["id"] == puid:
user = u
break
if not user:
return await msg.answer("Вы пытаетесь выгнать пользователя, которого нет в беседе.")
self.votes[msg.chat_id] = set()
members = len(msg.meta["data_chat"]["chat_info"]["users"])
if members < 10:
maximum = members - 1
elif members < 16:
maximum = 6
elif members < 22:
maximum = 8
else:
maximum = 10
return asyncio.ensure_future(self.do_vote(msg, f"Кик пользователя: {user['first_name']} {user['last_name']}", maximum, kick=puid))