def get_profile_by_name(args, filter_chat=None) -> Profile: """ Получение пользователя по имени/фамилии/имени и фамилии/никнейма/ид """ if not args: raise PWarning("Отсутствуют аргументы") if isinstance(args, str): args = [args] users = Profile.objects if filter_chat: users = users.filter(chats=filter_chat) if len(args) >= 2: user = users.filter(name=args[0].capitalize(), surname=args[1].capitalize()) else: user = users.filter(nickname_real=args[0].capitalize()) if len(user) == 0: user = users.filter(name=args[0].capitalize()) if len(user) == 0: user = users.filter(surname=args[0].capitalize()) if len(user) > 1: raise PWarning("2 и более пользователей подходит под поиск") if len(user) == 0: raise PWarning("Пользователь не найден. Возможно опечатка или он мне ещё ни разу не писал") return user.first()
def get_youtube_video(self, url): ydl_params = {'outtmpl': '%(id)s%(ext)s', 'logger': NothingLogger()} ydl = youtube_dl.YoutubeDL(ydl_params) ydl.add_default_info_extractors() try: video_info = ydl.extract_info(url, download=False) except youtube_dl.utils.DownloadError: raise PWarning("Не смог найти видео по этой ссылке") if video_info['duration'] > 60: raise PWarning("Нельзя грузить видосы > 60 секунд с ютуба") video_urls = [ x for x in video_info['formats'] if x['ext'] == 'mp4' and x.get('asr') ] if len(video_urls) == 0: raise PWarning( "Чёт проблемки, напишите разрабу и пришли ссылку на видео") max_quality_video = sorted(video_urls, key=lambda x: x['format_note'], reverse=True)[0] url = max_quality_video['url'] video_content = requests.get(url).content attachments = [ self.bot.upload_video(video_content, peer_id=self.event.peer_id) ] return attachments, video_info['title']
def start(self): audio_messages = self.event.get_all_attachments(VoiceAttachment) audio_message = audio_messages[0] download_url = audio_message.get_download_url() response = requests.get(download_url, stream=True) i = io.BytesIO(response.content) i.seek(0) o = io.BytesIO() o.name = "recognition.wav" try: input_file_format = download_url.split('.')[-1] if input_file_format == 'oga': input_file_format = 'ogg' except Exception: input_file_format = 'mp3' AudioSegment.from_file(i, input_file_format).export(o, format='wav') o.seek(0) r = sr.Recognizer() with sr.AudioFile(o) as source: audio = r.record(source) try: msg = r.recognize_google(audio, language='ru_RU') return msg except sr.UnknownValueError: raise PWarning("Ничего не понял((") except sr.RequestError as e: print(str(e)) raise PWarning("Проблема с форматом")
def get_sub(self, filters, for_delete=False): if self.event.chat: yt_subs = YoutubeSubscribe.objects.filter(chat=self.event.chat) if self.event.chat.admin != self.event.sender: yt_subs = yt_subs.filter(author=self.event.sender) else: yt_subs = YoutubeSubscribe.objects.filter(author=self.event.sender) if for_delete: yt_subs = yt_subs.filter(chat__isnull=True) for _filter in filters: yt_subs = yt_subs.filter(title__icontains=_filter) yt_subs_count = yt_subs.count() if yt_subs_count == 0: raise PWarning("Не нашёл :(") elif yt_subs_count == 1: return yt_subs.first() else: filters_str = " ".join(filters) for yt_sub in yt_subs: if yt_sub.title == filters_str: return yt_sub yt_subs = yt_subs[:10] yt_subs_titles = [yt_sub.title for yt_sub in yt_subs] yt_subs_titles_str = ";\n".join(yt_subs_titles) msg = f"Нашёл сразу {yt_subs_count}. уточните:\n\n" \ f"{yt_subs_titles_str}" + '.' if yt_subs_count > 10: msg += "\n..." raise PWarning(msg)
def get_photo_results(self, query): count = 5 gcs_api = GoogleCustomSearchAPI() urls = gcs_api.get_images_urls(query) if len(urls) == 0: raise PWarning("Ничего не нашёл по картинкам") attachments = [] if self.event.platform == Platform.VK: attachments = self.bot.upload_photos(urls, count, peer_id=self.event.peer_id) elif self.event.platform == Platform.TG: for url in urls: self.bot.set_activity(self.event.peer_id, ActivitiesEnum.UPLOAD_PHOTO) try: attachments.append(self.bot.upload_image_to_tg_server(url)) except PWarning: continue if len(attachments) == count: break else: attachments = self.bot.upload_photos(urls, 5) if len(attachments) == 0: raise PWarning("Ничего не нашёл по картинкам") return {'attachments': attachments}
def _check_allowed_url(self, url): parsed_url = urlparse(url) if not parsed_url.hostname: raise PWarning("Не нашёл ссылку на youtube видео") if parsed_url.hostname.replace('www.', '').lower() not in self.ALLOWED_URLS: raise PWarning("Это ссылка не на youtube/coub видео")
def start(self): with lock: gamer = self.bot.get_gamer_by_profile(self.event.sender) min_gamers = int( len(Profile.objects.filter(chats=self.event.chat)) / 2) if min_gamers < 2: min_gamers = 2 rates_gamers = RateModel.objects.filter(chat=self.event.chat) existed_rate = rates_gamers.filter(gamer=gamer) rate_gamer_str = "" for rate_gamer in rates_gamers: if rate_gamer.random: rate_gamer_str += f"{str(rate_gamer.gamer)} - {rate_gamer.rate} (R)\n" else: rate_gamer_str += f"{str(rate_gamer.gamer)} - {rate_gamer.rate}\n" if len(existed_rate) > 0: raise PWarning(f"Ставка уже поставлена\n" f"Игроки {len(rates_gamers)}/{min_gamers}:\n" f"{rate_gamer_str}") if self.event.message.args: random = False arg = self.event.message.args[0] self.check_number_arg_range(arg, 1, 100) else: random = True available_list = [x for x in range(1, 101)] rates = RateModel.objects.filter(chat=self.event.chat) for rate_entity in rates: available_list.pop(available_list.index(rate_entity.rate)) if len(available_list) == 0: raise PWarning( "Какая-то жесть, 100 игроков в ставке, я не могу больше придумать чисел, играйте((" ) arg = random_event(available_list) existed_another_rate = RateModel.objects.filter( chat=self.event.chat, rate=arg) if len(existed_another_rate) > 0: raise PWarning("Эта ставка уже поставлена другим игроком") RateModel( **{ 'gamer': gamer, 'chat': self.event.chat, 'rate': arg, 'random': random }).save() if random: rate_gamer_str += f"{gamer} - {arg} (R)\n" else: rate_gamer_str += f"{gamer} - {arg}\n" return f"Игроки {len(rates_gamers) + 1}/{min_gamers}:\n" \ f"{rate_gamer_str}"
def get_from_db(field_name, _type): my_field = {field_name + "__isnull": False, 'type': _type} try: word = getattr(Words.objects.filter(**my_field).order_by('?').first(), field_name).lower() except AttributeError: raise PWarning("Нет такого слова :(") except Exception as e: raise PWarning("Нет такого слова :(\n" f"Ошибка - {str(e)}") return word
def check_platforms(self): """ Проверка на вид платформы :return: bool """ if self.event.platform in self.excluded_platforms: error = f"Команда недоступна для {self.event.platform.value.upper()}" raise PWarning(error) if self.event.platform not in self.platforms: error = f"Команда недоступна для {self.event.platform.value.upper()}" raise PWarning(error) return True
def get_tiktok_video(self, url): headers = { 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } content = requests.get(url, headers=headers).content bs4 = BeautifulSoup(content, 'html.parser') try: video_url = bs4.find('meta', attrs={ 'property': 'og:video' }).attrs['content'] except: data_str = bs4.find("script", attrs={ "id": "sigi-persisted-data" }).text regexp = re.compile(r"window\['\w*'\]=") keys_positions = re.finditer(regexp, data_str) key = -1 pos = -1 data = {} for x in keys_positions: if pos != -1: data[key] = json.loads(data_str[pos:x.regs[0][0] - 1]) regexp = r"\['\w*'\]" key = re.findall(regexp, data_str[x.regs[0][0]:x.regs[0][1]])[0] \ .replace("[", '') \ .replace("]", "") \ .strip("'") \ .strip('\\') if key != -1: pos = x.regs[0][1] data[key] = json.loads(data_str[pos:len(data_str)]) if not data or "SIGI_STATE" not in data: raise PWarning("Не смог распарсить Тикток видео") try: video_url = data['SIGI_STATE']['ItemList']['video'][ 'preloadList'][0]['url'] except: raise PWarning("Не смог распарсить Тикток видео") title = bs4.find('meta', attrs={ 'property': 'og:title' }).attrs['content'] video = requests.get(video_url, headers=headers).content attachments = [ self.bot.upload_video(video, peer_id=self.event.peer_id) ] return attachments, title
def get_one_meme(memes, filter_list, approved=True) -> MemeModel: if len(memes) == 0: raise PWarning("Не нашёл :(") elif len(memes) == 1: return memes.first() elif not approved: return memes.first() else: filters_str = " ".join(filter_list) for meme in memes: if meme.name == filters_str: return meme raise PWarning("Под запрос подходит 2 и более мема")
def get_method_and_chosen_url(self, source): method = None urls = get_urls_from_text(source) for url in urls: hostname = urlparse(url).hostname if not hostname: raise PWarning("Не нашёл ссылки") for k in self.MEDIA_TRANSLATOR: if hostname in k: return self.MEDIA_TRANSLATOR[k], url if not method: raise PWarning("Не youtube/tiktok/reddit/instagram ссылка")
def start(self): if not self.event.sender.check_role(Role.TRUSTED) and \ len(NotifyModel.objects.filter(user=self.event.user)) >= 5: raise PWarning("Нельзя добавлять более 5 напоминаний") timezone = self.event.sender.city.timezone.name date, args_count, exact_time_flag = get_time( self.event.message.args[0], self.event.message.args[1], self.event.sender.city.timezone) if args_count == 2: self.check_args(3) if not date: raise PWarning("Не смог распарсить дату") date = normalize_datetime(date, timezone) datetime_now = localize_datetime(datetime.utcnow(), "UTC") if (date - datetime_now).seconds < 60: raise PWarning("Нельзя добавлять напоминание на ближайшую минуту") if not exact_time_flag and ((date - datetime_now).days < 0 or (datetime_now - date).seconds < 0): date = date + timedelta(days=1) if (date - datetime_now).days < 0 or (datetime_now - date).seconds < 0: raise PWarning("Нельзя указывать дату в прошлом") text = self.event.message.args_str_case.split(' ', args_count)[args_count] if text[0] == '/': first_space = text.find(' ') if first_space > 0: command = text[1:first_space] else: command = text[1:] from apps.bot.commands.NotifyRepeat import NotifyRepeat if command in self.full_names or command in NotifyRepeat( ).full_names: text = f"/обосрать {self.event.sender.name}" notify_datetime = localize_datetime(remove_tz(date), timezone) notify = NotifyModel( date=date, text=text, user=self.event.user, chat=self.event.chat, text_for_filter=notify_datetime.strftime("%d.%m.%Y %H:%M") + " " + text) notify.save() notify.text_for_filter += f" ({notify.id})" notify.save() return f'Сохранил на дату {str(notify_datetime.strftime("%d.%m.%Y %H:%M"))}'
def get_instagram_attachment(self, url): r = requests.get(url) bs4 = BeautifulSoup(r.content, 'html.parser') if bs4.find("html", {'class': "not-logged-in"}): raise PWarning("Требуется логин для скачивания") if 'reel' in url: content_type = 'reel' else: try: content_type = bs4.find('meta', attrs={ 'name': 'medium' }).attrs['content'] except Exception: raise PWarning("Ссылка на инстаграмм не является видео/фото") if content_type == 'image': photo_url = bs4.find('meta', attrs={ 'property': 'og:image' }).attrs['content'] return self.bot.upload_photos([photo_url], peer_id=self.event.peer_id), "" elif content_type == 'video': try: video_url = bs4.find('meta', attrs={ 'property': 'og:video' }).attrs['content'] except: raise PWarning("Не получилось распарсить видео с инстаграма") return [ self.bot.upload_video(video_url, peer_id=self.event.peer_id) ], "" elif content_type == 'reel': shared_data_text = "window._sharedData = " script_text = ";</script>" pos_start = r.text.find(shared_data_text) + len(shared_data_text) pos_end = r.text.find(script_text, pos_start) reel_data = json.loads(r.text[pos_start:pos_end]) entry_data = reel_data['entry_data'] if 'LoginAndSignupPage' in entry_data: raise PWarning( "Этот reel скачать не получится, требуется авторизация :(") video_url = entry_data['PostPage'][0]['graphql'][ 'shortcode_media']['video_url'] return [ self.bot.upload_video(video_url, peer_id=self.event.peer_id) ], "" else: raise PWarning("Ссылка на инстаграмм не является видео/фото")
def start(self): attachments = self.event.get_all_attachments(PhotoAttachment) if len(attachments) == 0: raise PWarning("Не нашёл в сообщении фотографий") attachments_url = [attachment.get_download_url() for attachment in attachments] attachments = self.bot.upload_photos(attachments_url, peer_id=self.event.peer_id) return {'attachments': attachments}
def get_terraria_server_by_version(version): if version is None: return terraria_servers[0] for terraria_server in terraria_servers: if version == str(terraria_server.version): return terraria_server raise PWarning("Я не знаю такой версии")
def find_item_by_label(items, label): label_lower = label.lower() for item in items: for sub_item in item['sub_items']: if sub_item['label'].lower() == label_lower: return sub_item raise PWarning(f"Не нашёл устройства с именем {label}")
def menu_default(self): warning_message = None id_name = self.get_id_or_meme_name(self.event.message.args) if isinstance(id_name, int): meme = self.get_meme(_id=id_name) else: memes = self.get_filtered_memes(self.event.message.args) try: meme = self.get_one_meme(memes, self.event.message.args) except PWarning: tanimoto_memes = self.get_tanimoto_memes( memes, " ".join(self.event.message.args)) if len(tanimoto_memes) == 0: raise PWarning("Не нашёл :(") meme = tanimoto_memes[0] warning_message = self.get_similar_memes_names(tanimoto_memes) meme.uses += 1 meme.save() prepared_meme = self.prepare_meme_to_send(meme) if warning_message: if self.event.platform == Platform.TG: return [prepared_meme, get_tg_formatted_text(warning_message)] return [prepared_meme, warning_message] return prepared_meme
def menu_rename(self): self.check_sender(Role.MODERATOR) self.check_args(3) self.int_args = [1] self.parse_int() meme = self.get_meme(_id=self.event.message.args[1]) new_name_list = self.event.message.args[2:] self.check_meme_name_is_no_digits(new_name_list) new_name = " ".join(new_name_list) try: MemeModel.objects.get(name=new_name) raise PWarning("Мем с таким названием уже есть") except MemeModel.DoesNotExist: pass user_msg = f'Мем с названием "{meme.name}" переименован.\n' \ f'Новое название - "{new_name}"' meme.name = new_name meme.save() if meme.author != self.event.sender: user = meme.author.get_user_by_default_platform() bot = get_bot_by_platform(user.get_platform_enum()) bot.parse_and_send_msgs(user_msg, user.user_id) return user_msg
def menu_confirm(self): self.check_sender(Role.MODERATOR) if len(self.event.message.args) == 1: meme = self.get_meme(approved=False) meme_to_send = self.prepare_meme_to_send(meme) meme_to_send['text'] = f"{meme.author}\n" \ f"{meme.name} ({meme.id})" return meme_to_send self.check_args(2) meme_filter = self.get_default_meme_filter_by_args( self.event.message.args[1:]) meme = self.get_meme(**meme_filter) if meme.approved: raise PWarning("Мем уже подтверждён") user_msg = f'Мем с названием "{meme.name}" подтверждён.' user = meme.author.get_user_by_default_platform() bot = get_bot_by_platform(user.get_platform_enum()) bot.parse_and_send_msgs(user_msg, user.user_id) msg = f'Мем "{meme.name}" ({meme.id}) подтверждён' meme.approved = True meme.save() return msg
def start(self): add_word = "бля" if self.event.message.args_str: add_word = self.event.message.args_str msgs = [x.message.raw for x in self.event.fwd if x.message] if not msgs: return add_word new_msg = "\n\n".join(msgs).strip() if not new_msg: raise PWarning("Нет текста в сообщении или пересланных сообщениях") symbols_first_priority = ['...'] symbols_left = ['.', ',', '?', '!', ':'] symbols_right = [' —', ' -'] flag = False if new_msg[-1] not in symbols_left: new_msg += '.' flag = True for symbol in symbols_first_priority: new_msg = new_msg.replace(symbol, " " + add_word + symbol) for symbol in symbols_left: new_msg = new_msg.replace(symbol, " " + add_word + symbol) for symbol in symbols_right: new_msg = new_msg.replace(symbol, " " + add_word + " " + symbol) if flag: new_msg = new_msg[:-1] return new_msg
def get_minecraft_version_by_args(version): if version is None: return minecraft_servers[0] for minecraft_server in minecraft_servers: if version in minecraft_server.names: return minecraft_server raise PWarning("Я не знаю такой версии")
def get_notifies_from_object(notifies_obj, timezone, print_username=False): if len(notifies_obj) == 0: raise PWarning("Нет напоминаний") result = "" for notify in notifies_obj: if notify.date: notify_datetime = localize_datetime(remove_tz(notify.date), timezone) else: notify_datetime = notify.crontab if print_username: result += f"{notify.user}\n" if notify.repeat: if notify.crontab: result += f"{notify_datetime} - Постоянное" else: result += f"{str(notify_datetime.strftime('%H:%M'))} - Постоянное" else: result += f"{str(notify_datetime.strftime('%d.%m.%Y %H:%M'))} - Постоянное" if notify.chat: result += f" (Конфа - {notify.chat.name})" result += f"\n{notify.text}\n\n" result_without_mentions = result.replace('@', '@_') return result_without_mentions
def add_phrase_before(recipient, word, field_name): if field_name[1] == '1': return f"{recipient}, ты {word}" elif field_name[1] == 'm': return f"{recipient}, вы {word}" else: raise PWarning("Ошибка определения числа и рода")
def send_weather_request(self): params = {'lat': self.city.lat, 'lon': self.city.lon, 'lang': 'ru_RU'} response = requests.get(self.URL, params, headers=self.HEADERS).json() if 'status' in response: if response['status'] == 403: raise PWarning( "На сегодня я исчерпал все запросы к Yandex Weather :(") fact = response['fact'] weather = { 'now': { 'temp': fact['temp'], 'temp_feels_like': fact['feels_like'], 'condition': fact['condition'], 'wind_dir': fact['wind_dir'], 'wind_speed': fact['wind_speed'], 'wind_gust': fact['wind_gust'], 'pressure': fact['pressure_mm'], 'humidity': fact['humidity'], }, 'forecast': [] } # Проставление part_name для времени сейчас index = list(DAY_TRANSLATOR.keys()).index( response['forecast']['parts'][0]['part_name']) weather['now']['part_name'] = list(DAY_TRANSLATOR.keys())[index - 1] for x in response['forecast']['parts']: weather['forecast'].append({ 'part_name': x['part_name'], 'temp_min': x['temp_min'], 'temp_max': x['temp_max'], 'temp_feels_like': x['feels_like'], 'condition': x['condition'], 'wind_dir': x['wind_dir'], 'wind_speed': x['wind_speed'], 'wind_gust': x['wind_gust'], 'pressure': x['pressure_mm'], 'humidity': x['humidity'], 'prec_mm': x['prec_mm'], 'prec_period': int(int(x['prec_period']) / 60), 'prec_prob': x['prec_prob'], }) return weather
def set_item_state(item_name, state): state_translated = ON_OFF_TRANSLATOR.get(state) if state_translated is None: raise PWarning(f"Я не знаю состояния {state}") item_name = " ".join(item_name) oh3 = Openhab3API() oh3.set_item_state(item_name, state_translated) return f"Поменял состояние на {state}"
def get_active_rates(self): if self.event.is_from_chat: rrs = RouletteRate.objects.filter(chat=self.event.chat) else: rrs = RouletteRate.objects.filter(chat__isnull=True, gamer=self.gamer) if len(rrs) == 0: raise PWarning("Ставок нет") return rrs
def start(self): try: if self.event.message.args: self.int_args = [0] self.parse_int() page = self.event.message.args[0] else: page = 1 memes = MemeModel.objects.filter(approved=True) p = Paginator(memes, 20) if page <= 0: page = 1 if page > p.num_pages: page = p.num_pages msg_header = f"Страница {page}/{p.num_pages}" memes_on_page = p.page(page) meme_names = get_memes_names(memes_on_page, self.event.sender) msg_body = ";\n".join(meme_names) if len(meme_names) > 0: msg_body += '.' if page != p.num_pages: on_last_page = p.per_page * page else: on_last_page = p.count msg_footer = f'----{p.per_page * (page - 1) + 1}-{on_last_page}----' if self.event.platform == Platform.TG: text = f"{msg_header}\n{get_tg_formatted_text(msg_body)}\n{msg_footer}" else: text = f"{msg_header}\n\n{msg_body}\n\n{msg_footer}" return text except PWarning: memes = MemeModel.objects.filter(approved=True) for arg in self.event.message.args: memes = memes.filter(name__icontains=arg) if len(memes) == 0: raise PWarning("Не нашёл мемов по заданному запросу") meme_command = Meme(bot=self.bot) memes = meme_command.get_tanimoto_memes(memes, self.event.message.args) memes_sliced = memes[:20] meme_names = get_memes_names(memes_sliced, self.event.sender) meme_names_str = ";\n".join(meme_names) if len(memes) > len(memes_sliced): meme_names_str += "\n..." elif len(memes) > 0: meme_names_str += '.' if self.event.platform == Platform.TG: text = f"{get_tg_formatted_text(meme_names_str)}\nВсего - {len(memes)}" else: text = f"{meme_names_str}\n\nВсего - {len(memes)}" return text
def get_joke(self, _type=1): params = {'CType': _type} response = requests.get(self.URL, params, timeout=10) if response.status_code != 200: raise PWarning("Чёто не работает. Пинайте этого лентяя") # Потому что от апи ответ гавённый и не jsonится return response.text.replace('{"content":"', '').replace('"}', '')
def update_profile_avatar(self, profile: Profile, user_id): response = self.requests.get('getUserProfilePhotos', {'user_id': user_id}) photos = response.json()['result']['photos'] if len(photos) == 0: raise PWarning("Нет фотографий в профиле") pa = PhotoAttachment() pa.parse_tg_photo(photos[0][-1], self) profile.set_avatar(pa.private_download_url)