linkkf 로직수정중
This commit is contained in:
BIN
lib/support/.DS_Store
vendored
Normal file
BIN
lib/support/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -10,15 +10,19 @@ def d(data):
|
||||
|
||||
from .logger import get_logger
|
||||
|
||||
logger = get_logger()
|
||||
#logger = get_logger()
|
||||
import logging
|
||||
logger = logging.getLogger('support')
|
||||
|
||||
from .base.aes import SupportAES
|
||||
from .base.discord import SupportDiscord
|
||||
from .base.file import SupportFile
|
||||
from .base.os_command import SupportOSCommand
|
||||
from .base.string import SupportString
|
||||
from .base.sub_process import SupportSubprocess
|
||||
from .base.support_sc import SupportSC
|
||||
from .base.telegram import SupportTelegram
|
||||
from .base.slack import SupportSlack
|
||||
from .base.util import (AlchemyEncoder, SingletonClass, SupportUtil,
|
||||
default_headers, pt)
|
||||
from .base.yaml import SupportYaml
|
||||
|
||||
@@ -18,8 +18,8 @@ class SupportAES(object):
|
||||
def encrypt(cls, raw, mykey=None):
|
||||
try:
|
||||
Random.atfork()
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
raw = pad(raw)
|
||||
@@ -31,8 +31,8 @@ class SupportAES(object):
|
||||
cipher = AES.new(key if mykey is None else mykey, AES.MODE_CBC, iv )
|
||||
try:
|
||||
tmp = cipher.encrypt( raw )
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
tmp = cipher.encrypt( raw.encode() )
|
||||
ret = base64.b64encode( iv + tmp )
|
||||
@@ -64,8 +64,8 @@ class SupportAES(object):
|
||||
def encrypt_(cls, raw, mykey=None, iv=None):
|
||||
try:
|
||||
Random.atfork()
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
raw = pad(raw)
|
||||
if type(raw) == type(''):
|
||||
@@ -79,8 +79,8 @@ class SupportAES(object):
|
||||
cipher = AES.new(key if mykey is None else mykey, AES.MODE_CBC, iv )
|
||||
try:
|
||||
tmp = cipher.encrypt( raw )
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
tmp = cipher.encrypt( raw.encode() )
|
||||
ret = base64.b64encode( tmp )
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import io
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
@@ -11,31 +10,36 @@ try:
|
||||
except:
|
||||
os.system('pip3 install discord-webhook')
|
||||
|
||||
# 2023-10-13 by flaskfarm
|
||||
# 웹훅 URL이 git에 노출되면 중단.
|
||||
# base64로 인코딩.
|
||||
import base64
|
||||
|
||||
from discord_webhook import DiscordEmbed, DiscordWebhook
|
||||
|
||||
from . import logger
|
||||
|
||||
webhook_list = [
|
||||
#'https://discord.com/api/webhooks/933908493612744705/DGPWBQN8LiMnt2cnCSNVy6rCc5Gi_vj98QpJ3ZEeihohzsfOsCWvcixJU1A2fQuepGFq', # 1
|
||||
#'https://discord.com/api/webhooks/932754078839234731/R2iFzQ7P8IKV-MGWp820ToWX07s5q8X-st-QsUJs7j3JInUj6ZlI4uDYKeR_cwIi98mf', # 2
|
||||
#'https://discord.com/api/webhooks/932754171835351131/50RLrYa_B69ybk4BWoLruNqU7YlZ3pl3gpPr9bwuankWyTIGtRGbgf0CJ9ExJWJmvXwo', # 3
|
||||
'https://discord.com/api/webhooks/794661043863027752/A9O-vZSHIgfQ3KX7wO5_e2xisqpLw5TJxg2Qs1stBHxyd5PK-Zx0IJbAQXmyDN1ixZ-n', # 4
|
||||
'https://discord.com/api/webhooks/810373348776476683/h_uJLBBlHzD0w_CG0nUajFO-XEh3fvy-vQofQt1_8TMD7zHiR7a28t3jF-xBCP6EVlow', # 5
|
||||
'https://discord.com/api/webhooks/810373405508501534/wovhf-1pqcxW5h9xy7iwkYaf8KMDjHU49cMWuLKtBWjAnj-tzS1_j8RJ7tsMyViDbZCE', # 6
|
||||
'https://discord.com/api/webhooks/796558388326039552/k2VV356S1gKQa9ht-JuAs5Dqw5eVkxgZsLUzFoxmFG5lW6jqKl7zCBbbKVhs3pcLOetm', # 7
|
||||
'https://discord.com/api/webhooks/810373566452858920/Qf2V8BoLOy2kQzlZGHy5HZ1nTj7lK72ol_UFrR3_eHKEOK5fyR_fQ8Yw8YzVh9EQG54o', # 8
|
||||
'https://discord.com/api/webhooks/810373654411739157/SGgdO49OCkTNIlc_BSMSy7IXQwwXVonG3DsVfvBVE6luTCwvgCqEBpEk30WBeMMieCyI', # 9
|
||||
'https://discord.com/api/webhooks/810373722341900288/FwcRJ4YxYjpyHpnRwF5f2an0ltEm8JPqcWeZqQi3Qz4QnhEY-kR2sjF9fo_n6stMGnf_', # 10
|
||||
'https://discord.com/api/webhooks/931779811691626536/vvwCm1YQvE5tW4QJ4SNKRmXhQQrmOQxbjsgRjbTMMXOSiclB66qipiZaax5giAqqu2IB', # 11
|
||||
'https://discord.com/api/webhooks/931779905631420416/VKlDwfxWQPJfIaj94-ww_hM1MNEayRKoMq0adMffCC4WQS60yoAub_nqPbpnfFRR3VU5', # 12
|
||||
'https://discord.com/api/webhooks/931779947914231840/22amQuHSOI7wPijSt3U01mXwd5hTo_WHfVkeaowDQMawCo5tXVfeEMd6wAWf1n7CseiG', # 13
|
||||
'https://discord.com/api/webhooks/810374294416654346/T3-TEdKIg7rwMZeDzNr46KPDvO7ZF8pRdJ3lfl39lJw2XEZamAG8uACIXagbNMX_B0YN', # 14
|
||||
'https://discord.com/api/webhooks/810374337403289641/_esFkQXwlPlhxJWtlqDAdLg2Nujo-LjGPEG3mUmjiRZto69NQpkBJ0F2xtSNrCH4VAgb', # 15
|
||||
'https://discord.com/api/webhooks/810374384736534568/mH5-OkBVpi7XqJioaQ8Ma-NiL-bOx7B5nYJpL1gZ03JaJaUaIW4bCHeCt5O_VGLJwAtj', # 16
|
||||
'https://discord.com/api/webhooks/810374428604104724/Z1Tdxz3mb0ytWq5LHWi4rG5CeJnr9KWXy5aO_waeD0NcImQnhRXe7h7ra7UrIDRQ2jOg', # 17
|
||||
'https://discord.com/api/webhooks/810374475773509643/QCPPN4djNzhuOmbS3DlrGBunK0SVR5Py9vMyCiPL-0T2VPgitFZS4YM6GCLfM2fkrn4-', # 18
|
||||
'https://discord.com/api/webhooks/810374527652855819/5ypaKI_r-hYzwmdDlVmgAU6xNgU833L9tFlPnf3nw4ZDaPMSppjt77aYOiFks4KLGQk8', # 19
|
||||
'https://discord.com/api/webhooks/810374587917402162/lHrG7CEysGUM_41DMnrxL2Q8eh1-xPjJXstYE68WWfLQbuUAV3rOfsNB9adncJzinYKi', # 20
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MTkwMTk2NzE1NTMwNS9uY01aaWZVVDY3ZTRISXdPeG8xM0dLdFBTNFBnVjZZSDBZaU1SQ2FMQkNfMU0yMHo3WmNFRjExM2xnY0NpRTFFdnhEZQ==').decode('utf-8'), # 1
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MjY1NjQwOTA3MTY0Ni9zUjlHZFJMbERrQV9Cc243UkdvQXQ3TmVSMU9SVFRxczVqUEc5UU9PYTJCbjllTTI1YnctV0FXZ2pYT1pYa183U0V4Wg==').decode('utf-8'), # 2
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MjkyNDExOTA0NDE4OC9wX3ZMN211eElKUmFWOXRDVG56S3c4LVJjY0R5V1JaSjdER2dYc1YwaXlLVGFjZEM4MVBiYmctWHFzY0NDTk5jdXpWeQ==').decode('utf-8'), # 3
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MzE2MjE1ODI0MzkwMS9KdDMwZjlTTTR6dWNfVmYwSVlmbzdZNTluOFI5T2RQazNXdTFtNG93MHZxZFJERXlneVZvb25Rdm1QbVRya1lOVTRyag==').decode('utf-8'), # 4
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MzMyNzY1MzE1ODk4Mi82Nk0zZVFyRGpSZG1UTzExaXZlMGhlTFFpNGwtckZUN1lRYTJ3elpmMjNBOGZPYm1CYjJSRmhxR2dNSHNlNUdHSFNLTA==').decode('utf-8'), # 5
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MzU1ODAzNzg5MzIxNC84aWFNLTJIdXJFOW1XM0RqY293dm9tUVhUeUxLOElrbWR5SnhsY1BFRzJ4MjBqOTNIN0FWNnY0dVJIak5XeGprcjg4Tw==').decode('utf-8'), # 6
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1MzczMTQzNDYxMDc0OS9xRktGX0hSWDRYVHFYMVFPRzM5YWNJVkp6dmdRZXBzZjM2TEFEUlpNOWtiZ0pNUHVfd091OXZ4bXdZVVBRMUpkUjhhRg==').decode('utf-8'), # 7
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1Mzg1NTI0NjI3NDYwMS9vWGVxYVdhWENNZktkM19iZktEVjB0Ti1XQzUyLUxpVjU0VjQxWE1jNWd3XzJmQnpnekp4MzJNYS1wOWlvQkFpd1I3Mw==').decode('utf-8'), # 8
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1Mzk5MDgyNzE1MTQ2MS85a0xXTXZCY1FaNzZRcnRpZmVJck9DOXo5SXl1WGl4YnRmbldocHVjSlFRVUJqcGxSd0tIdzdDc0h3THJhQkRQM1h5ag==').decode('utf-8'), # 9
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDExMjQ1NzYzNzg5OC9ZVC1qblZTeWFxcjAxMjFtWUtVZFU1SjJaVFZHS0NOM2djUDI2RXEwWm5hR3RWeFllM3NZa0kyUG81RWhPd211WDd6aw==').decode('utf-8'), # 10
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDI1Mzg1MTk1NTMxMS9RVUt1cU5uWFFiaWkwU01FMWxkU0lEakxhZXh5RDRUZEZuLWdXejFuSXRlYy1mSFVCU3dxUDd3WHNBbDB1dXd2VVJTRw==').decode('utf-8'), # 11
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDM3NDMyNDgxMzkyNS9VR1Jsc3liY2dPQ3hoMVQ1Z0J0QVc2RGQyZ0dPaGVOXzcydy15QTBvZzU5aU1BcnB3WWxVRzhka0ZXTUxSVUZpaHFScw==').decode('utf-8'), # 12
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDUxNjE5NzI3Nzc2Ny9iOEFIN1FtY2JPSl9XcUVHZmtMOVNPbXBJMWluVThvcDF4amQwWGFjRXFFZW82ZURzbS0yYkpZYllmQ1RYclMxbHhUdQ==').decode('utf-8'), # 13
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDY0MDIzMTIzOTcwMS90bkFSTzFvYWo1SWRmb0U4UEVJejRZUVMxNFhKXzdpc0I5Q1otdzVyaXdDN0U0cVVzQ1B6V2pLRnM3WE9OazBvVEo5Qg==').decode('utf-8'), # 14
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDc1NTcxNzIwMTk4MS9WLWQwc0hvNl9QakJTdFpLVmtuSTdDS0RuQks1QzRhS2dPZUZ4azEwam41VE5oZk1PdFNOSFNHN3BpaGNWLVh6Y0kxZg==').decode('utf-8'), # 15
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NDg4NDc4NDMyNDYxOS9XVEpHWWVjcjVKOHhtN0hTaUpCbmdnU01Uc3JkMUxiaDVwQzB2Vm5tYVptZWlvd2RRZWZQRHRuZHowRmViWE9xYkNoeA==').decode('utf-8'), # 16
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NTAxMTIxMzA5OTEyOS9neHVVenpsMTBpMUV4NWZtdU5jZGlOQ2FocHBEM3liQlpxaTR3Y3phdlpGeG1OUGx2VFRadU9CalZCMTBOZzJ2QWpLcA==').decode('utf-8'), # 17
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NTEzMjg4OTczMTE1My9YcTU4cXdCTGlOOEF4S1djQTl0MFJERkhIT0NDNjg4MlQ1aXBKbkJxY3VSOFVxMGowSzF4Rko3dUZWaGhRR0RFTjc3bw==').decode('utf-8'), # 18
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NTI5NzYzNzc5MzgxMy9pV3hoZkxRN190dHhkNENIVnNPWjA2ZHFOUjlkVTZUdlNfdHA2OHVnNlI2WmRIa2dESzJKb28xUVNSa3NrRDhLUXRyTg==').decode('utf-8'), # 19
|
||||
base64.b64decode(b'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTM5NDk1NTQ0NDk0MjAxMjQ4OC9zandtaFNDYjI0ZElYbjBVMWhwMmdJRzZDV2REcC1Kb3M0OW1Oc05jQllGenNDNm1KYVZJOVpoQm11dGt4cXd1bDc1ZA==').decode('utf-8'), # 20
|
||||
]
|
||||
|
||||
|
||||
@@ -44,20 +48,60 @@ class SupportDiscord(object):
|
||||
@classmethod
|
||||
def send_discord_message(cls, text, image_url=None, webhook_url=None):
|
||||
try:
|
||||
"""
|
||||
webhook = DiscordWebhook(url=webhook_url, content=text)
|
||||
if image_url is not None:
|
||||
embed = DiscordEmbed()
|
||||
embed.set_timestamp()
|
||||
embed.set_image(url=image_url)
|
||||
webhook.add_embed(embed)
|
||||
response = webhook.execute()
|
||||
return True
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
"""
|
||||
try:
|
||||
|
||||
if image_url is not None:
|
||||
webhook = DiscordWebhook(url=webhook_url)
|
||||
embed = DiscordEmbed()
|
||||
embed.set_timestamp()
|
||||
embed.set_image(url=image_url)
|
||||
tmp = text.split('\n', 1)
|
||||
embed.set_title(tmp[0])
|
||||
embed.set_description(tmp[1])
|
||||
webhook.add_embed(embed)
|
||||
else:
|
||||
if 'http://' in text or 'https://' in text:
|
||||
webhook = DiscordWebhook(url=webhook_url, content= text)
|
||||
else:
|
||||
webhook = DiscordWebhook(url=webhook_url, content='```' + text + '```')
|
||||
webhook.execute()
|
||||
return True
|
||||
except:
|
||||
webhook = DiscordWebhook(url=webhook_url, content=text)
|
||||
if image_url is not None:
|
||||
embed = DiscordEmbed()
|
||||
embed.set_timestamp()
|
||||
embed.set_image(url=image_url)
|
||||
webhook.add_embed(embed)
|
||||
webhook.execute()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
|
||||
@classmethod
|
||||
def send_discord_bot_message(cls, text, webhook_url, encryped=True):
|
||||
try:
|
||||
from support import SupportAES
|
||||
if encryped:
|
||||
text = '^' + SupportAES.encrypt(text)
|
||||
return cls.send_discord_message(text, webhook_url=webhook_url)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def discord_proxy_image(cls, image_url, webhook_url=None, retry=True):
|
||||
@@ -95,21 +139,21 @@ class SupportDiscord(object):
|
||||
return image_url
|
||||
else:
|
||||
raise Exception(str(data))
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
if retry:
|
||||
time.sleep(1)
|
||||
return cls.discord_proxy_image(image_url, webhook_url=None, retry=False)
|
||||
return cls.discord_proxy_image(image_url, webhook_url=webhook_url, retry=False)
|
||||
else:
|
||||
return image_url
|
||||
|
||||
|
||||
@classmethod
|
||||
def discord_proxy_image_localfile(cls, filepath, retry=True):
|
||||
def discord_proxy_image_localfile(cls, filepath, webhook_url=None, retry=True):
|
||||
data = None
|
||||
webhook_url = webhook_list[random.randint(0,len(webhook_list)-1)]
|
||||
|
||||
if webhook_url is None or webhook_url == '':
|
||||
webhook_url = webhook_list[random.randint(0,len(webhook_list)-1)]
|
||||
try:
|
||||
webhook = DiscordWebhook(url=webhook_url, content='')
|
||||
import io
|
||||
@@ -133,8 +177,8 @@ class SupportDiscord(object):
|
||||
if retry:
|
||||
time.sleep(1)
|
||||
return cls.discord_proxy_image_localfile(filepath, retry=False)
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if retry:
|
||||
@@ -143,15 +187,15 @@ class SupportDiscord(object):
|
||||
|
||||
|
||||
@classmethod
|
||||
def discord_proxy_image_bytes(cls, bytes, retry=True):
|
||||
def discord_proxy_image_bytes(cls, bytes, retry=True, format='jpg', webhook_url=None):
|
||||
data = None
|
||||
idx = random.randint(0,len(webhook_list)-1)
|
||||
webhook_url = webhook_list[idx]
|
||||
if webhook_url is None or webhook_url == '':
|
||||
webhook_url = webhook_list[random.randint(0,len(webhook_list)-1)]
|
||||
try:
|
||||
webhook = DiscordWebhook(url=webhook_url, content='')
|
||||
webhook.add_file(file=bytes, filename='image.jpg')
|
||||
webhook.add_file(file=bytes, filename=f'image.{format}')
|
||||
embed = DiscordEmbed()
|
||||
embed.set_image(url="attachment://image.jpg")
|
||||
embed.set_image(url=f"attachment://image.{format}")
|
||||
response = webhook.execute()
|
||||
data = None
|
||||
if type(response) == type([]):
|
||||
@@ -168,8 +212,8 @@ class SupportDiscord(object):
|
||||
if retry:
|
||||
time.sleep(1)
|
||||
return cls.discord_proxy_image_bytes(bytes, retry=False)
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if retry:
|
||||
@@ -181,7 +225,7 @@ class SupportDiscord(object):
|
||||
|
||||
# RSS에서 자막 올린거
|
||||
@classmethod
|
||||
def discord_cdn(cls, byteio=None, filepath=None, filename=None, webhook_url=None, content='', retry=True):
|
||||
def discord_cdn(cls, byteio=None, filepath=None, filename=None, webhook_url="https://discord.com/api/webhooks/1050549730964410470/ttge1ggOfIxrCSeTmYbIIsUWyMGAQj-nN6QBgwZTqLcHtUKcqjZ8wFWSWAhHmZne57t7", content='', retry=True):
|
||||
data = None
|
||||
if webhook_url is None:
|
||||
webhook_url = webhook_list[random.randint(0,9)]
|
||||
@@ -210,8 +254,8 @@ class SupportDiscord(object):
|
||||
if retry:
|
||||
time.sleep(1)
|
||||
return cls.discord_proxy_image_localfile(filepath, retry=False)
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
if retry:
|
||||
time.sleep(1)
|
||||
|
||||
@@ -3,6 +3,7 @@ import json
|
||||
import os
|
||||
import re
|
||||
import traceback
|
||||
import zipfile
|
||||
|
||||
from . import logger
|
||||
|
||||
@@ -16,8 +17,8 @@ class SupportFile(object):
|
||||
data = ifp.read()
|
||||
ifp.close()
|
||||
return data
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
@classmethod
|
||||
@@ -27,8 +28,8 @@ class SupportFile(object):
|
||||
ofp = codecs.open(filename, mode, encoding='utf8')
|
||||
ofp.write(data)
|
||||
ofp.close()
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
@classmethod
|
||||
@@ -37,8 +38,8 @@ class SupportFile(object):
|
||||
with open(filepath, "r", encoding='utf8') as json_file:
|
||||
data = json.load(json_file)
|
||||
return data
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
@classmethod
|
||||
@@ -48,8 +49,8 @@ class SupportFile(object):
|
||||
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
||||
with open(filepath, "w", encoding='utf8') as json_file:
|
||||
json.dump(data, json_file, indent=4, ensure_ascii=False)
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@@ -71,8 +72,8 @@ class SupportFile(object):
|
||||
response = requests.get(url, headers=headers) # get request
|
||||
file_is.write(response.content) # write to file
|
||||
return True
|
||||
except Exception as exception:
|
||||
logger.debug('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.debug(f"Exception:{str(e)}")
|
||||
logger.debug(traceback.format_exc())
|
||||
return False
|
||||
|
||||
@@ -82,118 +83,18 @@ class SupportFile(object):
|
||||
#text = text.replace('/', '')
|
||||
# 2021-07-31 X:X
|
||||
#text = text.replace(':', ' ')
|
||||
text = re.sub('[\\/:*?\"<>|]', ' ', text).strip()
|
||||
text = re.sub('[\\/:*?\"<>|:]', ' ', text).strip()
|
||||
text = re.sub("\s{2,}", ' ', text)
|
||||
return text
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def size(cls, start_path = '.'):
|
||||
total_size = 0
|
||||
for dirpath, dirnames, filenames in os.walk(start_path):
|
||||
for f in filenames:
|
||||
fp = os.path.join(dirpath, f)
|
||||
if not os.path.islink(fp):
|
||||
total_size += os.path.getsize(fp)
|
||||
return total_size
|
||||
def unzip(cls, zip_filepath, extract_folderpath):
|
||||
with zipfile.ZipFile(zip_filepath, 'r') as zip_ref:
|
||||
zip_ref.extractall(extract_folderpath)
|
||||
|
||||
|
||||
# 파일처리에서 사용. 중복이면 시간값
|
||||
@classmethod
|
||||
def file_move(cls, source_path, target_dir, target_filename):
|
||||
try:
|
||||
@@ -208,9 +109,160 @@ class SupportFile(object):
|
||||
new_target_filename = f"{tmp[0]} {str(time.time()).split('.')[0]}{tmp[1]}"
|
||||
target_path = os.path.join(target_dir, new_target_filename)
|
||||
shutil.move(source_path, target_path)
|
||||
except Exception as exception:
|
||||
logger.debug('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.debug(f"Exception:{str(e)}")
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def size(cls, start_path = '.'):
|
||||
if os.path.exists(start_path):
|
||||
if os.path.isdir(start_path):
|
||||
total_size = 0
|
||||
for dirpath, dirnames, filenames in os.walk(start_path):
|
||||
for f in filenames:
|
||||
fp = os.path.join(dirpath, f)
|
||||
if not os.path.islink(fp):
|
||||
total_size += os.path.getsize(fp)
|
||||
return total_size
|
||||
else:
|
||||
return os.path.getsize(start_path)
|
||||
return 0
|
||||
|
||||
|
||||
@classmethod
|
||||
def size_info(cls, start_path = '.'):
|
||||
ret = {
|
||||
'size':0,
|
||||
'file_count':0,
|
||||
'folder_count':0.
|
||||
}
|
||||
for dirpath, dirnames, filenames in os.walk(start_path):
|
||||
for f in filenames:
|
||||
fp = os.path.join(dirpath, f)
|
||||
if not os.path.islink(fp):
|
||||
ret['size'] += os.path.getsize(fp)
|
||||
ret['folder_count'] += len(dirnames)
|
||||
ret['file_count'] += len(filenames)
|
||||
return ret
|
||||
|
||||
|
||||
@classmethod
|
||||
def rmtree(cls, folderpath):
|
||||
import shutil
|
||||
try:
|
||||
for root, dirs, files in os.walk(folderpath):
|
||||
for name in files:
|
||||
os.remove(os.path.join(root, name))
|
||||
for name in dirs:
|
||||
shutil.rmtree(os.path.join(root, name))
|
||||
shutil.rmtree(folderpath)
|
||||
except Exception as e:
|
||||
logger.debug(f"Exception:{str(e)}")
|
||||
logger.debug(traceback.format_exc())
|
||||
return False
|
||||
|
||||
|
||||
@classmethod
|
||||
def file_move(cls, source_path, target_dir, target_filename):
|
||||
try:
|
||||
import shutil
|
||||
import time
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
target_path = os.path.join(target_dir, target_filename)
|
||||
if source_path != target_path:
|
||||
if os.path.exists(target_path):
|
||||
tmp = os.path.splitext(target_filename)
|
||||
new_target_filename = f"{tmp[0]} {str(time.time()).split('.')[0]}{tmp[1]}"
|
||||
target_path = os.path.join(target_dir, new_target_filename)
|
||||
shutil.move(source_path, target_path)
|
||||
except Exception as e:
|
||||
logger.debug(f"Exception:{str(e)}")
|
||||
logger.debug(traceback.format_exc())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
@classmethod
|
||||
@@ -234,13 +286,13 @@ class SupportFile(object):
|
||||
import shutil
|
||||
shutil.rmtree(zip_path)
|
||||
return zipfilepath
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
@classmethod
|
||||
def rmtree(cls, folderpath):
|
||||
import shutil
|
||||
@@ -253,19 +305,9 @@ class SupportFile(object):
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def rmtree2(cls, folderpath):
|
||||
import shutil
|
||||
try:
|
||||
for root, dirs, files in os.walk(folderpath):
|
||||
for name in files:
|
||||
os.remove(os.path.join(root, name))
|
||||
for name in dirs:
|
||||
shutil.rmtree(os.path.join(root, name))
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -279,8 +321,8 @@ class SupportFile(object):
|
||||
try:
|
||||
with open(filename, 'wb') as f:
|
||||
f.write(data)
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@@ -361,8 +403,8 @@ class SupportFile(object):
|
||||
if isinstance(data, bytes):
|
||||
data = data.decode('utf-8')
|
||||
return data
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
"""
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import os, sys, traceback, requests
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
from io import BytesIO
|
||||
|
||||
import requests
|
||||
|
||||
from . import logger
|
||||
|
||||
|
||||
class SupportImage(object):
|
||||
|
||||
@classmethod
|
||||
@@ -20,6 +26,6 @@ class SupportImage(object):
|
||||
from . import SupportDiscord
|
||||
return SupportDiscord.discord_proxy_image_bytes(img_byte_arr)
|
||||
except Exception as e:
|
||||
logger.error('Exception:%s', e)
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
44
lib/support/base/os_command.py
Normal file
44
lib/support/base/os_command.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
import platform
|
||||
|
||||
from . import logger
|
||||
|
||||
|
||||
class SupportOSCommand(object):
|
||||
|
||||
@classmethod
|
||||
def get_size(cls, path):
|
||||
from support import SupportFile, SupportSubprocess, SupportUtil
|
||||
if platform.system() == 'Windows':
|
||||
#https://docs.microsoft.com/en-us/sysinternals/downloads/du
|
||||
"""
|
||||
bin = r'C:\SJVA3\data\bin\du64.exe'
|
||||
command = [bin, '-c', '-nobanner', f'"{path}"']
|
||||
data = ToolSubprocess.execute_command_return(command, force_log=True)
|
||||
logger.warning(data)
|
||||
ret = {}
|
||||
tmp = data.split('\t')
|
||||
ret['target'] = tmp[1].strip()
|
||||
ret['size'] = int(tmp[0].strip())
|
||||
ret['sizeh'] = ToolUtil.sizeof_fmt(ret['size'])
|
||||
"""
|
||||
ret = {}
|
||||
ret['target'] = path
|
||||
if os.path.exists(path):
|
||||
if os.path.isdir(path):
|
||||
ret['size'] = SupportFile.size(start_path=path)
|
||||
else:
|
||||
ret['size'] = os.stat(path).st_size
|
||||
ret['sizeh'] = SupportUtil.sizeof_fmt(ret['size'])
|
||||
return ret
|
||||
|
||||
else:
|
||||
command = ['du', '-bs', path]
|
||||
data = SupportSubprocess.execute_command_return(command)
|
||||
ret = {}
|
||||
tmp = data['log'].split('\t')
|
||||
ret['target'] = tmp[1].strip()
|
||||
ret['size'] = int(tmp[0].strip())
|
||||
ret['sizeh'] = SupportUtil.sizeof_fmt(ret['size'])
|
||||
return ret
|
||||
|
||||
25
lib/support/base/slack.py
Normal file
25
lib/support/base/slack.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from slack_sdk.webhook import WebhookClient
|
||||
except:
|
||||
os.system('pip3 install slack-sdk')
|
||||
from slack_sdk.webhook import WebhookClient
|
||||
from . import logger
|
||||
|
||||
class SupportSlack:
|
||||
@classmethod
|
||||
def send_slack_message(cls, text, webhook_url=None, image_url=None, disable_notification=None):
|
||||
try:
|
||||
if webhook_url is None:
|
||||
return False
|
||||
webhook = WebhookClient(webhook_url)
|
||||
if image_url is not None:
|
||||
webhook.send(text=text, blocks=[{"type": "image", "title": {"type": "plain_text", "text": "Image", "emoji": True}, "image_url": image_url, "alt_text": "Image"}])
|
||||
webhook.send(text=text)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -1,3 +1,6 @@
|
||||
import re
|
||||
import traceback
|
||||
|
||||
from . import logger
|
||||
|
||||
|
||||
@@ -5,22 +8,78 @@ class SupportString(object):
|
||||
@classmethod
|
||||
def get_cate_char_by_first(cls, title): # get_first
|
||||
value = ord(title[0].upper())
|
||||
if value >= ord('0') and value <= ord('9'): return '0Z'
|
||||
elif value >= ord('A') and value <= ord('Z'): return '0Z'
|
||||
elif value >= ord('가') and value < ord('나'): return '가'
|
||||
elif value < ord('다'): return '나'
|
||||
elif value < ord('라'): return '다'
|
||||
elif value < ord('마'): return '라'
|
||||
elif value < ord('바'): return '마'
|
||||
elif value < ord('사'): return '바'
|
||||
elif value < ord('아'): return '사'
|
||||
elif value < ord('자'): return '아'
|
||||
elif value < ord('차'): return '자'
|
||||
elif value < ord('카'): return '차'
|
||||
elif value < ord('타'): return '카'
|
||||
elif value < ord('파'): return '타'
|
||||
elif value < ord('하'): return '파'
|
||||
elif value <= ord('힣'): return '하'
|
||||
else: return '0Z'
|
||||
if ord('가') <= value < ord('나'): return '가'
|
||||
if ord('나') <= value < ord('다'): return '나'
|
||||
if ord('다') <= value < ord('라'): return '다'
|
||||
if ord('라') <= value < ord('마'): return '라'
|
||||
if ord('마') <= value < ord('바'): return '마'
|
||||
if ord('바') <= value < ord('사'): return '바'
|
||||
if ord('사') <= value < ord('아'): return '사'
|
||||
if ord('아') <= value < ord('자'): return '아'
|
||||
if ord('자') <= value < ord('차'): return '자'
|
||||
if ord('차') <= value < ord('카'): return '차'
|
||||
if ord('카') <= value < ord('타'): return '카'
|
||||
if ord('타') <= value < ord('파'): return '타'
|
||||
if ord('파') <= value < ord('하'): return '파'
|
||||
if ord('하') <= value < ord('힣'): return '하'
|
||||
return '0Z'
|
||||
|
||||
|
||||
@classmethod
|
||||
def is_include_hangul(cls, text):
|
||||
try:
|
||||
hanCount = len(re.findall(u'[\u3130-\u318F\uAC00-\uD7A3]+', text))
|
||||
return hanCount > 0
|
||||
except:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def language_info(cls, text):
|
||||
try:
|
||||
text = text.strip().replace(' ', '')
|
||||
all_count = len(text)
|
||||
han_count = len(re.findall('[\u3130-\u318F\uAC00-\uD7A3]', text))
|
||||
eng_count = len(re.findall('[a-zA-Z]', text))
|
||||
etc_count = len(re.findall('[0-9]', text))
|
||||
etc_count += len(re.findall('[-=+,#/\?:^$.@*\"※~&%ㆍ!』\\‘|\(\)\[\]\<\>`\'…》:]', text))
|
||||
if all_count == etc_count:
|
||||
return (0,0)
|
||||
han_percent = int(han_count * 100 / (all_count-etc_count))
|
||||
eng_percent = int(eng_count * 100 / (all_count-etc_count))
|
||||
return (han_percent, eng_percent)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def remove_special_char(cls, text):
|
||||
return re.sub('[-=+,#/\?:^$.@*\"※~&%ㆍ!』\\‘|\(\)\[\]\<\>`\'…》:]', '', text)
|
||||
|
||||
|
||||
@classmethod
|
||||
def remove_emoji(cls, text, char=''):
|
||||
import re
|
||||
emoji_pattern = re.compile("["
|
||||
u"\U0001F600-\U0001F64F" # emoticons
|
||||
u"\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
u"\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
u"\U00002500-\U00002BEF" # chinese char
|
||||
u"\U00002702-\U000027B0"
|
||||
u"\U00002702-\U000027B0"
|
||||
#u"\U000024C2-\U0001F251"
|
||||
u"\U0001f926-\U0001f937"
|
||||
u"\U00010000-\U0010ffff"
|
||||
u"\u2640-\u2642"
|
||||
u"\u2600-\u2B55"
|
||||
u"\u200d"
|
||||
u"\u23cf"
|
||||
u"\u23e9"
|
||||
u"\u231a"
|
||||
u"\ufe0f" # dingbats
|
||||
u"\u3030"
|
||||
"]+", flags=re.UNICODE)
|
||||
# Remove emojis from the text
|
||||
text = emoji_pattern.sub(char, text)
|
||||
return text
|
||||
@@ -1,5 +1,6 @@
|
||||
import io
|
||||
import json
|
||||
import locale
|
||||
import os
|
||||
import platform
|
||||
import queue
|
||||
@@ -20,7 +21,7 @@ def demote(user_uid, user_gid):
|
||||
class SupportSubprocess(object):
|
||||
|
||||
@classmethod
|
||||
def command_for_windows(cls, command: list) -> str or list:
|
||||
def command_for_windows(cls, command: list):
|
||||
if platform.system() == 'Windows':
|
||||
tmp = []
|
||||
if type(command) == type([]):
|
||||
@@ -43,17 +44,32 @@ class SupportSubprocess(object):
|
||||
|
||||
iter_arg = ''
|
||||
if platform.system() == 'Windows':
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8')
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8', bufsize=0)
|
||||
else:
|
||||
if uid == None:
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8')
|
||||
else:
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, preexec_fn=demote(uid, gid), encoding='utf8')
|
||||
|
||||
|
||||
|
||||
new_ret = {'status':'finish', 'log':None}
|
||||
|
||||
def func(ret):
|
||||
with process.stdout:
|
||||
try:
|
||||
for line in iter(process.stdout.readline, iter_arg):
|
||||
ret.append(line.strip())
|
||||
if log:
|
||||
logger.debug(ret[-1])
|
||||
except:
|
||||
pass
|
||||
|
||||
result = []
|
||||
thread = threading.Thread(target=func, args=(result,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
#thread.join()
|
||||
|
||||
try:
|
||||
#process.communicate()
|
||||
process_ret = process.wait(timeout=timeout) # wait for the subprocess to exit
|
||||
except:
|
||||
import psutil
|
||||
@@ -62,14 +78,17 @@ class SupportSubprocess(object):
|
||||
proc.kill()
|
||||
process.kill()
|
||||
new_ret['status'] = "timeout"
|
||||
|
||||
ret = []
|
||||
with process.stdout:
|
||||
for line in iter(process.stdout.readline, iter_arg):
|
||||
ret.append(line.strip())
|
||||
if log:
|
||||
logger.debug(ret[-1])
|
||||
|
||||
#logger.error(process_ret)
|
||||
thread.join()
|
||||
#ret = []
|
||||
#with process.stdout:
|
||||
# for line in iter(process.stdout.readline, iter_arg):
|
||||
# ret.append(line.strip())
|
||||
# if log:
|
||||
# logger.debug(ret[-1])
|
||||
|
||||
ret = result
|
||||
#logger.error(ret)
|
||||
if format is None:
|
||||
ret2 = '\n'.join(ret)
|
||||
elif format == 'json':
|
||||
@@ -82,20 +101,29 @@ class SupportSubprocess(object):
|
||||
break
|
||||
ret2 = json.loads(''.join(ret[index:]))
|
||||
except:
|
||||
ret2 = None
|
||||
ret2 = ret
|
||||
|
||||
new_ret['log'] = ret2
|
||||
return new_ret
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
logger.error('command : %s', command)
|
||||
finally:
|
||||
try:
|
||||
if process.stdout:
|
||||
process.stdout.close()
|
||||
if process.stdin:
|
||||
process.stdin.close()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
__instance_list = []
|
||||
|
||||
|
||||
def __init__(self, command, print_log=False, shell=False, env=None, timeout=None, uid=None, gid=None, stdout_callback=None, call_id=None):
|
||||
def __init__(self, command, print_log=False, shell=False, env=None, timeout=None, uid=None, gid=None, stdout_callback=None, call_id=None, callback_line=True):
|
||||
self.command = command
|
||||
self.print_log = print_log
|
||||
self.shell = shell
|
||||
@@ -108,6 +136,7 @@ class SupportSubprocess(object):
|
||||
self.stdout_queue = None
|
||||
self.call_id = call_id
|
||||
self.timestamp = time.time()
|
||||
self.callback_line = callback_line
|
||||
|
||||
|
||||
def start(self, join=True):
|
||||
@@ -127,13 +156,15 @@ class SupportSubprocess(object):
|
||||
self.command = self.command_for_windows(self.command)
|
||||
logger.debug(f"{self.command=}")
|
||||
if platform.system() == 'Windows':
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
|
||||
else:
|
||||
if self.uid == None:
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
else:
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, preexec_fn=demote(self.uid, self.gid), encoding='utf8', bufsize=0)
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=self.shell, env=self.env, preexec_fn=demote(self.uid, self.gid), encoding='utf8', bufsize=0)
|
||||
SupportSubprocess.__instance_list.append(self)
|
||||
self.send_stdout_callback(self.call_id, 'START', None)
|
||||
self.__start_communicate()
|
||||
self.__start_send_callback()
|
||||
if self.process is not None:
|
||||
@@ -142,17 +173,18 @@ class SupportSubprocess(object):
|
||||
self.process_close()
|
||||
else:
|
||||
self.process.wait()
|
||||
self.remove_instance(self)
|
||||
logger.info(f"{self.command} END")
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(traceback.format_exc())
|
||||
logger.warning(self.command)
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('error', str(e))
|
||||
self.stdout_callback('error', str(traceback.format_exc()))
|
||||
self.send_stdout_callback(self.call_id, 'ERROR', str(e))
|
||||
self.send_stdout_callback(self.call_id, 'ERROR', str(traceback.format_exc()))
|
||||
finally:
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('thread_end', None)
|
||||
#self.stdout_callback(self.call_id, 'thread_end', None)
|
||||
pass
|
||||
|
||||
|
||||
def __start_communicate(self):
|
||||
@@ -164,7 +196,11 @@ class SupportSubprocess(object):
|
||||
|
||||
def rdr():
|
||||
while True:
|
||||
buf = self.process.stdout.read(1)
|
||||
try:
|
||||
buf = self.process.stdout.read(1)
|
||||
except:
|
||||
continue
|
||||
#print(buf)
|
||||
if buf:
|
||||
_queue.put( buf )
|
||||
else:
|
||||
@@ -192,7 +228,9 @@ class SupportSubprocess(object):
|
||||
if r is not None:
|
||||
#print(f"{r=}")
|
||||
self.stdout_queue.put(r)
|
||||
self.stdout_queue.put('\n')
|
||||
self.stdout_queue.put('<END>')
|
||||
self.stdout_queue.put('\n')
|
||||
for tgt in [rdr, clct]:
|
||||
th = threading.Thread(target=tgt)
|
||||
th.setDaemon(True)
|
||||
@@ -204,16 +242,36 @@ class SupportSubprocess(object):
|
||||
def func():
|
||||
while self.stdout_queue:
|
||||
line = self.stdout_queue.get()
|
||||
#logger.error(line)
|
||||
if line == '<END>':
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('end', None)
|
||||
self.send_stdout_callback(self.call_id, 'END', None)
|
||||
break
|
||||
else:
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('log', line)
|
||||
self.send_stdout_callback(self.call_id, 'LOG', line)
|
||||
self.remove_instance(self)
|
||||
|
||||
th = threading.Thread(target=func, args=())
|
||||
def func_callback_line():
|
||||
previous = ''
|
||||
while self.stdout_queue:
|
||||
receive = previous + self.stdout_queue.get()
|
||||
lines = receive.split('\n')
|
||||
previous = lines[-1]
|
||||
|
||||
for line in lines[:-1]:
|
||||
line = line.strip()
|
||||
# TODO
|
||||
#logger.error(line)
|
||||
if line == '<END>':
|
||||
self.send_stdout_callback(self.call_id, 'END', None)
|
||||
break
|
||||
else:
|
||||
self.send_stdout_callback(self.call_id, 'LOG', line)
|
||||
self.remove_instance(self)
|
||||
|
||||
if self.callback_line:
|
||||
th = threading.Thread(target=func_callback_line, args=())
|
||||
else:
|
||||
th = threading.Thread(target=func, args=())
|
||||
th.setDaemon(True)
|
||||
th.start()
|
||||
|
||||
@@ -243,6 +301,15 @@ class SupportSubprocess(object):
|
||||
self.process.stdin.write(f'{cmd}\n')
|
||||
self.process.stdin.flush()
|
||||
|
||||
def send_stdout_callback(self, call_id, mode, data):
|
||||
try:
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback(self.call_id, mode, data)
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(f"[{call_id}] [{mode}] [{data}]")
|
||||
#logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def all_process_close(cls):
|
||||
@@ -271,4 +338,7 @@ class SupportSubprocess(object):
|
||||
for instance in cls.__instance_list:
|
||||
if instance.call_id == call_id:
|
||||
return instance
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_list(cls):
|
||||
return cls.__instance_list
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import requests
|
||||
from telepot_mod import Bot
|
||||
|
||||
from . import logger
|
||||
@@ -12,11 +14,21 @@ class SupportTelegram:
|
||||
try:
|
||||
bot = Bot(bot_token)
|
||||
if image_url is not None:
|
||||
bot.sendPhoto(chat_id, image_url, disable_notification=disable_notification)
|
||||
logger.debug(image_url)
|
||||
for i in range(5):
|
||||
if requests.get(image_url).status_code == 200:
|
||||
break
|
||||
else:
|
||||
time.sleep(3)
|
||||
try:
|
||||
bot.sendPhoto(chat_id, image_url, disable_notification=disable_notification)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
bot.sendMessage(chat_id, text, disable_web_page_preview=True, disable_notification=disable_notification)
|
||||
return True
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
logger.debug('Chatid:%s', chat_id)
|
||||
return False
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import os, traceback, io, re, json, codecs
|
||||
import json
|
||||
import time
|
||||
import traceback
|
||||
from functools import wraps
|
||||
|
||||
from . import logger
|
||||
|
||||
from functools import wraps
|
||||
import time
|
||||
|
||||
def pt(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwds):
|
||||
@@ -26,9 +29,9 @@ class SupportUtil(object):
|
||||
def sizeof_fmt(cls, num, suffix='Bytes'):
|
||||
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
|
||||
if abs(num) < 1024.0:
|
||||
return "%3.1f%s%s" % (num, unit, suffix)
|
||||
return "%3.1f %s%s" % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return "%.1f%s%s" % (num, 'Y', suffix)
|
||||
return "%.1f %s%s" % (num, 'Y', suffix)
|
||||
|
||||
@classmethod
|
||||
def is_arm(cls):
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import os
|
||||
import traceback
|
||||
|
||||
import yaml
|
||||
|
||||
from . import logger
|
||||
|
||||
|
||||
class SupportYaml(object):
|
||||
@classmethod
|
||||
def write_yaml(cls, filepath, data):
|
||||
@@ -11,3 +17,41 @@ class SupportYaml(object):
|
||||
with open(filepath, encoding='utf8') as file:
|
||||
data = yaml.load(file, Loader=yaml.FullLoader)
|
||||
return data
|
||||
|
||||
|
||||
@classmethod
|
||||
def copy_section(cls, source_file, target_file, section_name):
|
||||
from support import SupportFile
|
||||
try:
|
||||
if os.path.exists(source_file) == False:
|
||||
return 'not_exist_source_file'
|
||||
if os.path.exists(target_file) == False:
|
||||
return 'not_exist_target_file'
|
||||
lines = SupportFile.read_file(source_file).split('\n')
|
||||
section = {}
|
||||
current_section_name = None
|
||||
current_section_data = None
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if line.startswith('# SECTION START : '):
|
||||
current_section_name = line.split(':')[1].strip()
|
||||
current_section_data = []
|
||||
if current_section_data is not None:
|
||||
current_section_data.append(line)
|
||||
if line.startswith('# SECTION END'):
|
||||
section[current_section_name] = current_section_data
|
||||
current_section_name = current_section_data = None
|
||||
|
||||
if section_name not in section:
|
||||
return 'not_include_section'
|
||||
|
||||
data = '\n'.join(section[section_name])
|
||||
source_data = SupportFile.read_file(target_file)
|
||||
source_data = source_data + f"\n{data}\n"
|
||||
SupportFile.write_file(target_file, source_data)
|
||||
return 'success'
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return 'exception'
|
||||
@@ -116,7 +116,11 @@ class SupportFfmpeg(object):
|
||||
header_count = 0
|
||||
if self.proxy is None:
|
||||
if self.headers is None:
|
||||
command = [self.__ffmpeg_path, '-y', '-i', self.url, '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
if platform.system() == 'Windows':
|
||||
command = [self.__ffmpeg_path, '-y', '-i', f'"{self.url}"', '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
else:
|
||||
command = [self.__ffmpeg_path, '-y', '-i', self.url, '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
|
||||
else:
|
||||
headers_command = []
|
||||
tmp = ""
|
||||
@@ -136,9 +140,15 @@ class SupportFfmpeg(object):
|
||||
if len(tmp) > 0:
|
||||
headers_command.append('-headers')
|
||||
headers_command.append(f'{tmp}')
|
||||
command = [self.__ffmpeg_path, '-y'] + headers_command + ['-i', self.url, '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
if platform.system() == 'Windows':
|
||||
command = [self.__ffmpeg_path, '-y'] + headers_command + ['-i', f'"{self.url}"', '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
else:
|
||||
command = [self.__ffmpeg_path, '-y'] + headers_command + ['-i', self.url, '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
else:
|
||||
command = [self.__ffmpeg_path, '-y', '-http_proxy', self.proxy, '-i', self.url, '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
if platform.system() == 'Windows':
|
||||
command = [self.__ffmpeg_path, '-y', '-http_proxy', self.proxy, '-i', f'"{self.url}"', '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
else:
|
||||
command = [self.__ffmpeg_path, '-y', '-http_proxy', self.proxy, '-i', self.url, '-c', 'copy', '-bsf:a', 'aac_adtstoasc']
|
||||
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
@@ -159,7 +169,7 @@ class SupportFfmpeg(object):
|
||||
return
|
||||
except:
|
||||
pass
|
||||
#logger.error(' '.join(command))
|
||||
logger.error(' '.join(command))
|
||||
command = SupportSubprocess.command_for_windows(command)
|
||||
|
||||
if platform.system() == 'Windows' and header_count > 1:
|
||||
@@ -216,8 +226,8 @@ SET CRLF=^
|
||||
else:
|
||||
if os.path.exists(self.temp_fullpath):
|
||||
os.remove(self.temp_fullpath)
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
arg = {'type':'last', 'status':self.status, 'data' : self.get_data()}
|
||||
@@ -347,6 +357,7 @@ SET CRLF=^
|
||||
return data
|
||||
|
||||
def send_to_listener(self, **arg):
|
||||
print(arg)
|
||||
if self.total_callback_function != None:
|
||||
self.total_callback_function(**arg)
|
||||
if self.callback_function is not None and self.callback_function != self.total_callback_function:
|
||||
|
||||
27
lib/support/expand/ffprobe.py
Normal file
27
lib/support/expand/ffprobe.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import traceback
|
||||
|
||||
from support import SupportSubprocess, logger
|
||||
|
||||
|
||||
class SupportFfprobe:
|
||||
__ffprobe_path = 'ffprobe'
|
||||
|
||||
@classmethod
|
||||
def initialize(cls, __ffprobe_path):
|
||||
cls.__ffprobe_path = __ffprobe_path
|
||||
|
||||
@classmethod
|
||||
def ffprobe(cls, filepath, ffprobe_path=None, option=None):
|
||||
try:
|
||||
if ffprobe_path == None:
|
||||
ffprobe_path = cls.__ffprobe_path
|
||||
|
||||
command = [ffprobe_path, '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', filepath]
|
||||
if option is not None:
|
||||
command += option
|
||||
logger.warning(' '.join(command))
|
||||
ret = SupportSubprocess.execute_command_return(command, format='json')
|
||||
return ret['log']
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
@@ -204,9 +204,9 @@ class GoogleSheetBase:
|
||||
break
|
||||
except gspread.exceptions.APIError:
|
||||
self.sleep_exception()
|
||||
except Exception as exception:
|
||||
except Exception as e:
|
||||
logger.error(f"{key} - {value}")
|
||||
logger.error('Exception:%s', exception)
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
logger.error(self.header_info)
|
||||
self.sleep_exception()
|
||||
|
||||
197
lib/support/expand/rclone.py
Normal file
197
lib/support/expand/rclone.py
Normal file
@@ -0,0 +1,197 @@
|
||||
import json
|
||||
import os
|
||||
import traceback
|
||||
|
||||
from support import SupportSubprocess, d, logger
|
||||
|
||||
|
||||
class SupportRclone(object):
|
||||
__instance_list = []
|
||||
|
||||
__rclone_path = 'rclone'
|
||||
__rclone_config_path = 'rclone.conf'
|
||||
|
||||
|
||||
@classmethod
|
||||
def initialize(cls, __rclone_path, __rclone_config_path):
|
||||
cls.__rclone_path = __rclone_path
|
||||
cls.__rclone_config_path = __rclone_config_path
|
||||
|
||||
@classmethod
|
||||
def get_rclone_path(cls):
|
||||
return cls.__rclone_path
|
||||
|
||||
@classmethod
|
||||
def __get_cmd(cls, config_path=None):
|
||||
command = [cls.__rclone_path]
|
||||
if config_path == None:
|
||||
command += ['--config', cls.__rclone_config_path]
|
||||
else:
|
||||
command += ['--config', config_path]
|
||||
return command
|
||||
|
||||
|
||||
@classmethod
|
||||
def rclone_cmd(cls):
|
||||
return [cls.__rclone_path, '--config', cls.__rclone_config_path]
|
||||
|
||||
@classmethod
|
||||
def get_version(cls, rclone_path=None):
|
||||
try:
|
||||
if rclone_path == None:
|
||||
rclone_path = cls.__rclone_path
|
||||
cmd = [rclone_path, '--version']
|
||||
result = SupportSubprocess.execute_command_return(cmd)
|
||||
if result != None and result['status'] == 'finish':
|
||||
return result['log']
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def config_list(cls, rclone_path=None, rclone_config_path=None, option=None):
|
||||
try:
|
||||
if rclone_path == None:
|
||||
rclone_path = cls.__rclone_path
|
||||
if rclone_config_path == None:
|
||||
rclone_config_path = cls.__rclone_config_path
|
||||
if os.path.exists(rclone_config_path) == False:
|
||||
return
|
||||
command = [rclone_path, '--config', rclone_config_path, 'config', 'dump']
|
||||
if option is not None:
|
||||
command += option
|
||||
result = SupportSubprocess.execute_command_return(command, format='json')
|
||||
for key, value in result['log'].items():
|
||||
if 'token' in value and value['token'].startswith('{'):
|
||||
value['token'] = json.loads(value['token'])
|
||||
return result['log']
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
@classmethod
|
||||
def get_config(cls, remote_name, rclone_path=None, rclone_config_path=None, option=None):
|
||||
try:
|
||||
data = cls.config_list(rclone_path=rclone_path, rclone_config_path=rclone_config_path, option=option)
|
||||
return data.get(remote_name, None)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def lsjson(cls, remote_path, config_path=None, option=None):
|
||||
return cls.__execute_one_param('lsjson', remote_path, config_path=config_path, option=option, format='json')
|
||||
|
||||
|
||||
@classmethod
|
||||
def lsf(cls, remote_path, config_path=None, option=None):
|
||||
if option == None:
|
||||
option = ['--max-depth=1']
|
||||
return cls.__execute_one_param('lsf', remote_path, config_path=config_path, option=option, format='json')
|
||||
|
||||
|
||||
@classmethod
|
||||
def size(cls, remote_path, config_path=None, option=None):
|
||||
if option == None:
|
||||
option = ['--json']
|
||||
return cls.__execute_one_param('size', remote_path, config_path=config_path, option=option, format='json')
|
||||
|
||||
|
||||
@classmethod
|
||||
def mkdir(cls, remote_path, config_path=None, option=None):
|
||||
return cls.__execute_one_param('mkdir', remote_path, config_path=config_path, option=option, format='json')
|
||||
|
||||
@classmethod
|
||||
def purge(cls, remote_path, config_path=None, option=None):
|
||||
return cls.__execute_one_param('purge', remote_path, config_path=config_path, option=option, format='json')
|
||||
|
||||
|
||||
@classmethod
|
||||
def __execute_one_param(cls, command, remote_path, config_path=None, option=None, format=None):
|
||||
try:
|
||||
command = cls.__get_cmd(config_path) + [command, remote_path]
|
||||
if option is not None:
|
||||
command += option
|
||||
result = SupportSubprocess.execute_command_return(command, format=format)
|
||||
ret = None
|
||||
if result != None and result['status'] == 'finish':
|
||||
ret = result['log']
|
||||
return ret
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def copy(cls, src, tar, config_path=None, option=None):
|
||||
return cls.__execute_two_param('copy', src, tar, config_path=config_path, option=option)
|
||||
|
||||
@classmethod
|
||||
def copy_server_side(cls, src, tar, config_path=None, option=None):
|
||||
if option == None:
|
||||
option = ['--drive-server-side-across-configs=true', '--delete-empty-src-dirs']
|
||||
return cls.__execute_two_param('copy', src, tar, config_path=config_path, option=option)
|
||||
|
||||
@classmethod
|
||||
def move(cls, src, tar, config_path=None, option=None):
|
||||
return cls.__execute_two_param('move', src, tar, config_path=config_path, option=option)
|
||||
|
||||
@classmethod
|
||||
def move_server_side(cls, src, tar, config_path=None, option=None):
|
||||
if option == None:
|
||||
option = ['--drive-server-side-across-configs=true', '--delete-empty-src-dirs']
|
||||
return cls.__execute_two_param('move', src, tar, config_path=config_path, option=option)
|
||||
|
||||
@classmethod
|
||||
def __execute_two_param(cls, command, src, tar, config_path=None, option=None, format=None):
|
||||
try:
|
||||
command = cls.__get_cmd(config_path) + [command, src, tar]
|
||||
if option is not None:
|
||||
command += option
|
||||
result = SupportSubprocess.execute_command_return(command, format=format)
|
||||
ret = None
|
||||
if result != None and result['status'] == 'finish':
|
||||
ret = result['log']
|
||||
return ret
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def getid(cls, remote_path, config_path=None, option=None):
|
||||
try:
|
||||
command = cls.__get_cmd(config_path) + ['backend', 'getid', remote_path]
|
||||
if option is not None:
|
||||
command += option
|
||||
result = SupportSubprocess.execute_command_return(command)
|
||||
ret = None
|
||||
if result != None and result['status'] == 'finish':
|
||||
ret = result['log']
|
||||
if ret is not None and (len(ret.split(' ')) > 1 or ret == ''):
|
||||
ret = None
|
||||
return ret
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def chpar(cls, src, tar, config_path=None, option=None):
|
||||
try:
|
||||
command = cls.__get_cmd(config_path) + ['backend', 'chpar', src, tar, '-o', 'depth=1', '-o', 'delete-empty-src-dir', '--drive-use-trash=false']
|
||||
if option is not None:
|
||||
command += option
|
||||
result = SupportSubprocess.execute_command_return(command)
|
||||
ret = None
|
||||
if result != None and result['status'] == 'finish':
|
||||
ret = result['log']
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
114
lib/support/expand/simple_selenium.py
Normal file
114
lib/support/expand/simple_selenium.py
Normal file
@@ -0,0 +1,114 @@
|
||||
import os
|
||||
|
||||
from support import d, logger
|
||||
|
||||
try:
|
||||
from selenium import webdriver
|
||||
except:
|
||||
os.system("pip install --upgrade selenium")
|
||||
from selenium import webdriver
|
||||
|
||||
import base64
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from selenium import webdriver
|
||||
from selenium.common.exceptions import UnexpectedAlertPresentException
|
||||
from selenium.webdriver.chrome.service import Service
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import Select, WebDriverWait
|
||||
from webdriver_manager.chrome import ChromeDriverManager
|
||||
|
||||
|
||||
class SupportSimpleSelenium(object):
|
||||
|
||||
def __init__(self, P, mode="local", headless=False, remote=None):
|
||||
self.P = P
|
||||
self.driver = None
|
||||
self.timeout = 5
|
||||
self.driver_init(mode=mode, headless=headless, remote=remote)
|
||||
|
||||
|
||||
def driver_init(self, mode='local', headless=False, remote=None):
|
||||
if mode == 'local':
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
options = Options()
|
||||
if headless:
|
||||
options.add_argument('headless')
|
||||
self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
|
||||
elif mode == 'remote':
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
options = Options()
|
||||
#options.set_preference("general.useragent.override", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
|
||||
#options.set_preference("general.platform.override", "Win32")
|
||||
self.driver = webdriver.Remote(remote, options=options)
|
||||
|
||||
|
||||
def get_pagesoruce(self, url, wait_xpath="/html/body", retry=True):
|
||||
try:
|
||||
self.driver.get(url)
|
||||
WebDriverWait(self.driver, self.timeout).until(lambda driver: driver.find_element(By.XPATH, wait_xpath))
|
||||
return self.driver.page_source
|
||||
except Exception as e:
|
||||
logger.error('Exception:%s', e)
|
||||
logger.error(traceback.format_exc())
|
||||
self.driver_quit()
|
||||
if retry:
|
||||
return self.get_pagesoruce(url, wait_xpath=wait_xpath, retry=False)
|
||||
|
||||
|
||||
def driver_quit(self):
|
||||
if self.driver != None:
|
||||
def func():
|
||||
self.driver.quit()
|
||||
self.driver = None
|
||||
#self.logger.debug('driver quit..')
|
||||
th = threading.Thread(target=func, args=())
|
||||
th.setDaemon(True)
|
||||
th.start()
|
||||
|
||||
def get_downloaded_files(self):
|
||||
if not self.driver.current_url.startswith("chrome://downloads"):
|
||||
self.driver.get("chrome://downloads/")
|
||||
#driver.implicitly_wait(4)
|
||||
self.driver.implicitly_wait(2)
|
||||
return self.driver.execute_script( \
|
||||
"return document.querySelector('downloads-manager') "
|
||||
" .shadowRoot.querySelector('#downloadsList') "
|
||||
" .items.filter(e => e.state === 'COMPLETE') "
|
||||
" .map(e => e.filePath || e.file_path || e.fileUrl || e.file_url); ")
|
||||
|
||||
|
||||
|
||||
def get_file_content(self, path):
|
||||
elem = self.driver.execute_script( \
|
||||
"var input = window.document.createElement('INPUT'); "
|
||||
"input.setAttribute('type', 'file'); "
|
||||
"input.hidden = true; "
|
||||
"input.onchange = function (e) { e.stopPropagation() }; "
|
||||
"return window.document.documentElement.appendChild(input); " )
|
||||
|
||||
elem._execute('sendKeysToElement', {'value': [ path ], 'text': path})
|
||||
|
||||
result = self.driver.execute_async_script( \
|
||||
"var input = arguments[0], callback = arguments[1]; "
|
||||
"var reader = new FileReader(); "
|
||||
"reader.onload = function (ev) { callback(reader.result) }; "
|
||||
"reader.onerror = function (ex) { callback(ex.message) }; "
|
||||
"reader.readAsDataURL(input.files[0]); "
|
||||
"input.remove(); "
|
||||
, elem)
|
||||
|
||||
if not result.startswith('data:') :
|
||||
raise Exception("Failed to get file content: %s" % result)
|
||||
|
||||
return base64.b64decode(result[result.find('base64,') + 7:])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# docker run -d --name selenium_chromium -it -p 4446:4444 -p 5902:5900 -p 7902:7900 --shm-size 2g seleniarm/standalone-chromium:latest
|
||||
BIN
lib/support/libsc/sc.cpython-311-aarch64-linux-gnu.so
Normal file
BIN
lib/support/libsc/sc.cpython-311-aarch64-linux-gnu.so
Normal file
Binary file not shown.
BIN
lib/support/libsc/sc.cpython-311_32.so
Normal file
BIN
lib/support/libsc/sc.cpython-311_32.so
Normal file
Binary file not shown.
BIN
lib/support/libsc/sc.cpython-311_64.so
Normal file
BIN
lib/support/libsc/sc.cpython-311_64.so
Normal file
Binary file not shown.
@@ -36,7 +36,7 @@ class CustomFormatter(logging.Formatter):
|
||||
# pathname filename
|
||||
#format = "[%(asctime)s|%(name)s|%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
|
||||
|
||||
__format = '[{yellow}%(asctime)s{reset}|{color}%(levelname)s{reset}|{green}%(name)s{reset} %(pathname)s:%(lineno)s] {color}%(message)s{reset}' if os.environ.get('LOGGER_PATHNAME', "False") == "True" else '[{yellow}%(asctime)s{reset}|{color}%(levelname)s{reset}|{green}%(name)s{reset} %(filename)s:%(lineno)s] {color}%(message)s{reset}'
|
||||
__format = '[{yellow}%(asctime)s{reset}|{color}%(levelname)s{reset}|{green}%(name)s{reset}|%(pathname)s:%(lineno)s] {color}%(message)s{reset}' if os.environ.get('LOGGER_PATHNAME', "False") == "True" else '[{yellow}%(asctime)s{reset}|{color}%(levelname)s{reset}|{green}%(name)s{reset}|%(filename)s:%(lineno)s] {color}%(message)s{reset}'
|
||||
|
||||
FORMATS = {
|
||||
logging.DEBUG: __format.format(color=grey, reset=reset, yellow=yellow, green=green),
|
||||
@@ -53,15 +53,13 @@ class CustomFormatter(logging.Formatter):
|
||||
|
||||
|
||||
def get_logger(name=None, log_path=None):
|
||||
if os.environ.get('FF') == 'true':
|
||||
name = 'framework'
|
||||
if name == None:
|
||||
name = sys.argv[0].rsplit('.', 1)[0]
|
||||
logger = logging.getLogger(name)
|
||||
if not logger.handlers:
|
||||
level = logging.DEBUG
|
||||
logger.setLevel(level)
|
||||
formatter = logging.Formatter(u'[%(asctime)s|%(levelname)s|%(filename)s:%(lineno)s] %(message)s')
|
||||
formatter = logging.Formatter(u'[%(asctime)s|%(levelname)s|%(name)s|%(filename)s:%(lineno)s] %(message)s')
|
||||
def customTime(*args):
|
||||
utc_dt = utc.localize(datetime.utcnow())
|
||||
my_tz = timezone("Asia/Seoul")
|
||||
|
||||
@@ -4,6 +4,7 @@ from support import SupportSC
|
||||
|
||||
try:
|
||||
if os.path.exists(os.path.join(os.path.dirname(__file__), 'tving.py')):
|
||||
#from .cppl import SupportCppl
|
||||
from .kakaotv import SupportKakaotv
|
||||
from .seezn import SupportSeezn
|
||||
from .tving import SupportTving
|
||||
@@ -13,5 +14,6 @@ try:
|
||||
SupportWavve = SupportSC.load_module_f(__file__, 'wavve').SupportWavve
|
||||
SupportSeezn = SupportSC.load_module_f(__file__, 'seezn').SupportSeezn
|
||||
SupportKakaotv = SupportSC.load_module_f(__file__, 'kakaotv').SupportKakaotv
|
||||
#SupportCppl = SupportSC.load_module_f(__file__, 'cppl').SupportCppl
|
||||
except:
|
||||
pass
|
||||
|
||||
1
lib/support/site/cppl.pyf
Normal file
1
lib/support/site/cppl.pyf
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user