socializer/src/sessionmanager/utils.py

104 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
""" Some utilities. I no have idea how I should put these, so..."""
import os
import re
import html
import logging
import requests
from pubsub import pub
log = logging.getLogger("utils")
url_re = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
bad_chars = '\'\\.,[](){}:;"'
def seconds_to_string(seconds, precision=0):
""" convert a number of seconds in a string representation."""
# ToDo: Improve it to handle properly Russian plurals.
day = seconds // 86400
hour = seconds // 3600
min = (seconds // 60) % 60
sec = seconds - (hour * 3600) - (min * 60)
sec_spec = "." + str(precision) + "f"
sec_string = sec.__format__(sec_spec)
string = ""
if day == 1:
string += _("%d day, ") % day
elif day >= 2:
string += _("%d days, ") % day
if (hour == 1):
string += _("%d hour, ") % hour
elif (hour >= 2):
string += _("%d hours, ") % hour
if (min == 1):
string += _("%d minute, ") % min
elif (min >= 2):
string += _("%d minutes, ") % min
if sec >= 0 and sec <= 2:
string += _("%s second") % sec_string
else:
string += _("%s seconds") % sec_string
return string
def find_urls_in_text(text):
return [s.strip(bad_chars) for s in url_re.findall(text)]
def download_file(url, local_filename):
r = requests.get(url, stream=True)
pub.sendMessage("change_status", status=_("Downloading {0}").format(local_filename,))
total_length = r.headers.get("content-length")
dl = 0
total_length = int(total_length)
with open(local_filename, 'wb') as f:
for chunk in r.iter_content(chunk_size=512*1024):
if chunk: # filter out keep-alive new chunks
dl += len(chunk)
f.write(chunk)
done = int(100 * dl/total_length)
msg = _("Downloading {0} ({1}%)").format(os.path.basename(local_filename), done)
# print(msg)
pub.sendMessage("change_status", status=msg)
pub.sendMessage("change_status", status=_("Ready"))
return local_filename
def download_files(downloads):
for download in downloads:
download_file(download[0], download[1])
def detect_users(text):
""" Detect all users and communities mentionned in any text posted in VK."""
# This regexp gets group and users mentionned in topic comments.
for matched_data in re.finditer("(\[)(id|club)(\d+:bp-\d+_\d+\|)(\D+)(\])", text):
text = re.sub("\[(id|club)\d+:bp-\d+_\d+\|\D+\]", matched_data.groups()[3]+", ", text, count=1)
# This is for users and communities just mentionned in wall comments or posts.
for matched_data in re.finditer("(\[)(id|club)(\d+\|)(\D+)(\])", text):
text = re.sub("\[(id|club)\d+\|\D+\]", matched_data.groups()[3]+", ", text, count=1)
return text
def clean_text(text):
""" Clean text, removing all unneeded HTMl and converting HTML represented characters in their unicode counterparts."""
text = detect_users(text)
text = html.unescape(text)
return text
def transform_audio_url(url):
""" Transforms the URL offered by VK to the unencrypted stream so we can still play it.
This function will be updated every time VK decides to change something in their Audio API'S.
Changelog:
30/04/2019: Re-enabled old methods as VK changed everything as how it was working on 16.04.2019.
17.04.2019: Updated function. Now it is not required to strip anything, just replacing /index.m3u8 with .mp3 should be enough.
16.04.2019: Implemented this function. For now it replaces /index.m3u8 by .mp3, also removes the path component before "/audios" if the URL contains the word /audios, or the last path component before the filename if doesn't.
"""
if "vkuseraudio.net" not in url and "index.m3u8" not in url:
return url
url = url.replace("/index.m3u8", ".mp3")
parts = url.split("/")
if "/audios" not in url:
url = url.replace("/"+parts[-2], "")
else:
url = url.replace("/"+parts[-3], "")
url = url.split(".mp3?")[0]+".mp3"
return url
def safe_filename(filename):
allowed_symbols = ["_", ".", ",", "-", "(", ")"]
return "".join([c for c in filename if c.isalpha() or c.isdigit() or c==' ' or c in allowed_symbols]).rstrip()