linkkf 로직수정중

This commit is contained in:
2025-12-25 19:42:32 +09:00
parent 695d26767e
commit af9a38a973
128 changed files with 8711 additions and 1484 deletions

BIN
lib/support/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -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

View File

@@ -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 )

View File

@@ -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)

View File

@@ -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())
"""

View File

@@ -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())

View 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
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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'

View File

@@ -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:

View 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())

View File

@@ -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()

View 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

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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")

View File

@@ -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

File diff suppressed because one or more lines are too long