Compare commits
3
Commits
main
...
v0.7-share-node
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3191cf2af0 | ||
|
|
7d3e1ae945 | ||
|
|
bfced5b4da |
+10
-2
@@ -202,6 +202,8 @@ def get_nodes_map():
|
||||
return json_data
|
||||
|
||||
|
||||
|
||||
|
||||
# 保存原始的 get 方法
|
||||
_original_request = aiohttp.ClientSession._request
|
||||
|
||||
@@ -270,6 +272,10 @@ async def mixlab_hander(request):
|
||||
print(e)
|
||||
return web.json_response(data)
|
||||
|
||||
# @routes.post('/test')
|
||||
# async def mixlab_hander(request):
|
||||
# test_auto()
|
||||
# return web.Response(text="test", status=200)
|
||||
|
||||
@routes.get('/mixlab/app')
|
||||
async def mixlab_app_handler(request):
|
||||
@@ -359,14 +365,14 @@ PromptServer.add_routes=new_add_routes
|
||||
|
||||
# 导入节点
|
||||
from .nodes.PromptNode import RandomPrompt
|
||||
from .nodes.ImageNode import NoiseImage,TransparentImage,LoadImagesFromPath,LoadImagesFromURL,ResizeImage,TextImage,SvgImage,Image3D,EmptyLayer,ShowLayer,NewLayer,MergeLayers,AreaToMask,SmoothMask,FeatheredMask,SplitLongMask,ImageCropByAlpha,EnhanceImage,FaceToMask
|
||||
from .nodes.ImageNode import NoiseImage,TransparentImage,LoadImagesFromPath,LoadImagesFromURL,UploadImageForSMMS,ResizeImage,TextImage,SvgImage,Image3D,EmptyLayer,ShowLayer,NewLayer,MergeLayers,AreaToMask,SmoothMask,FeatheredMask,SplitLongMask,ImageCropByAlpha,EnhanceImage,FaceToMask
|
||||
from .nodes.Vae import VAELoader,VAEDecode
|
||||
from .nodes.ScreenShareNode import ScreenShareNode,FloatingVideo
|
||||
from .nodes.Clipseg import CLIPSeg,CombineMasks
|
||||
from .nodes.ChatGPT import ChatGPTNode,ShowTextForGPT,CharacterInText
|
||||
from .nodes.Audio import GamePal,SpeechRecognition,SpeechSynthesis
|
||||
from .nodes.Utils import AppInfo,IntNumber,FloatSlider,TextInput,ColorInput,FontInput,TextToNumber,DynamicDelayProcessor,LimitNumber,SwitchByIndex,GetImageSize_,MultiplicationNode
|
||||
|
||||
from .nodes.ShareNode import ShareToWeibo
|
||||
|
||||
# 要导出的所有节点及其名称的字典
|
||||
# 注意:名称应全局唯一
|
||||
@@ -413,6 +419,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
"GetImageSize_":GetImageSize_,
|
||||
"SwitchByIndex":SwitchByIndex,
|
||||
"LimitNumber":LimitNumber,
|
||||
"UploadImageForSMMS":UploadImageForSMMS,
|
||||
"ShareToWeibo":ShareToWeibo
|
||||
# "GamePal":GamePal
|
||||
}
|
||||
|
||||
|
||||
@@ -4798,7 +4798,13 @@
|
||||
"VAELoaderConsistencyDecoder",
|
||||
"TextToNumber",
|
||||
"TextInput_",
|
||||
"DynamicDelayProcessor"
|
||||
"DynamicDelayProcessor",
|
||||
"MultiplicationNode",
|
||||
"ShareToWeibo",
|
||||
"LimitNumber",
|
||||
"SwitchByIndex",
|
||||
"UploadImageForSMMS",
|
||||
"GetImageSize_"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-mixlab-nodes"
|
||||
|
||||
+95
-3
@@ -560,7 +560,7 @@ def base64_to_image(base64_string):
|
||||
return image
|
||||
|
||||
|
||||
def create_temp_file(image):
|
||||
def create_temp_file(image,fn='material'):
|
||||
output_dir = folder_paths.get_temp_directory()
|
||||
|
||||
(
|
||||
@@ -569,7 +569,7 @@ def create_temp_file(image):
|
||||
counter,
|
||||
subfolder,
|
||||
_,
|
||||
) = folder_paths.get_save_image_path('material', output_dir)
|
||||
) = folder_paths.get_save_image_path(fn, output_dir)
|
||||
|
||||
|
||||
image=tensor2pil(image)
|
||||
@@ -586,6 +586,42 @@ def create_temp_file(image):
|
||||
"type": "temp"
|
||||
}]
|
||||
|
||||
def create_temp_file_for_upload(image,fn='tmp'):
|
||||
output_dir = folder_paths.get_temp_directory()
|
||||
|
||||
(
|
||||
full_output_folder,
|
||||
filename,
|
||||
counter,
|
||||
subfolder,
|
||||
_,
|
||||
) = folder_paths.get_save_image_path(fn, output_dir)
|
||||
|
||||
|
||||
image=tensor2pil(image)
|
||||
|
||||
image_file = f"{filename}_{counter:05}.png"
|
||||
|
||||
image_path=os.path.join(full_output_folder, image_file)
|
||||
|
||||
image.save(image_path,compress_level=4)
|
||||
|
||||
return image_path
|
||||
|
||||
|
||||
def upload_smms(fp,token):
|
||||
# print(json.dumps(res, indent=4))
|
||||
image_url=''
|
||||
try:
|
||||
headers = {'Authorization': token}
|
||||
files = {'smfile': open(fp, 'rb')}
|
||||
url = 'https://smms.app/api/v2/upload'
|
||||
res = requests.post(url, files=files, headers=headers).json()
|
||||
image_url=res['data']['url']
|
||||
except:
|
||||
print('upload error')
|
||||
return image_url
|
||||
|
||||
|
||||
class SmoothMask:
|
||||
@classmethod
|
||||
@@ -1676,4 +1712,60 @@ class ResizeImage:
|
||||
|
||||
im=pil2tensor(im)
|
||||
|
||||
return (im,)
|
||||
return (im,)
|
||||
|
||||
|
||||
|
||||
|
||||
class UploadImageForSMMS:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"image": ("IMAGE",),
|
||||
"token": ("STRING",{"multiline": False,"default": "","dynamicPrompts": False}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("url",)
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "♾️Mixlab/image"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
|
||||
def run(self,image,token):
|
||||
# print(image,token)
|
||||
fp=create_temp_file_for_upload(image)
|
||||
|
||||
url=upload_smms(fp,token)
|
||||
|
||||
return (url,)
|
||||
|
||||
|
||||
# 压缩到5M
|
||||
# from PIL import Image
|
||||
# import os
|
||||
|
||||
# def compress_image(input_image_path, output_image_path):
|
||||
# image = Image.open(input_image_path)
|
||||
# image.save(output_image_path, optimize=True, quality=50)
|
||||
|
||||
# def get_image_size(image_path):
|
||||
# return os.path.getsize(image_path) / (1024 * 1024) # 将文件大小从字节转换为兆字节
|
||||
|
||||
# def compress_to_5mb(input_image_path, output_image_path):
|
||||
# compress_image(input_image_path, output_image_path)
|
||||
# max_iterations = 10 # 设置最大循环次数
|
||||
# iterations = 0
|
||||
# while get_image_size(output_image_path) > 5 and iterations < max_iterations:
|
||||
# compress_image(output_image_path, output_image_path)
|
||||
# iterations += 1
|
||||
|
||||
# # 示例用法
|
||||
# input_image_path = "input.jpg"
|
||||
# output_image_path = "output.jpg"
|
||||
# compress_to_5mb(input_image_path, output_image_path)
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
import urllib.parse
|
||||
|
||||
|
||||
# 分享到微博
|
||||
class ShareToWeibo:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"title":("STRING",{"multiline": True,"default": "","dynamicPrompts": False}),
|
||||
"pic_url":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}),
|
||||
"url":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ()
|
||||
# RETURN_NAMES = ("number",)
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "♾️Mixlab/share"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_NODE = True
|
||||
# OUTPUT_IS_LIST = ()
|
||||
|
||||
def run(self, title, pic_url, url):
|
||||
encoded_title = urllib.parse.quote(title)
|
||||
encoded_pic_url = urllib.parse.quote(pic_url)
|
||||
encoded_url = urllib.parse.quote(url)
|
||||
url = "https://service.weibo.com/share/share.php?title={}&pic={}&url={}".format(encoded_title,encoded_pic_url,encoded_url)
|
||||
print(url)
|
||||
return {"ui": {"url": [url]}, "result": ()}
|
||||
|
||||
|
||||
|
||||
@@ -397,6 +397,7 @@ class AppInfo:
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def run(self,name,image,input_ids,output_ids,description,version):
|
||||
|
||||
@@ -524,3 +525,5 @@ class LimitNumber:
|
||||
|
||||
return (nn,)
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -3,4 +3,5 @@ pyOpenSSL
|
||||
watchdog
|
||||
opencv-python-headless
|
||||
matplotlib
|
||||
openai
|
||||
openai
|
||||
# playwright
|
||||
@@ -0,0 +1,110 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
import { $el } from '../../../scripts/ui.js'
|
||||
import { api } from '../../../scripts/api.js'
|
||||
|
||||
function get_position_style (ctx, widget_width, y, node_height) {
|
||||
const MARGIN = 12 // the margin around the html element
|
||||
|
||||
/* Create a transform that deals with all the scrolling and zooming */
|
||||
const elRect = ctx.canvas.getBoundingClientRect()
|
||||
const transform = new DOMMatrix()
|
||||
.scaleSelf(
|
||||
elRect.width / ctx.canvas.width,
|
||||
elRect.height / ctx.canvas.height
|
||||
)
|
||||
.multiplySelf(ctx.getTransform())
|
||||
.translateSelf(MARGIN, MARGIN + y)
|
||||
|
||||
return {
|
||||
transformOrigin: '0 0',
|
||||
transform: transform,
|
||||
left: `0`,
|
||||
top: `0`,
|
||||
cursor: 'pointer',
|
||||
position: 'absolute',
|
||||
maxWidth: `${widget_width - MARGIN * 2}px`,
|
||||
// maxHeight: `${node_height - MARGIN * 2}px`, // we're assuming we have the whole height of the node
|
||||
width: `${widget_width - MARGIN * 2}px`,
|
||||
// height: `${node_height * 0.3 - MARGIN * 2}px`,
|
||||
// background: '#EEEEEE',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
// alignItems: 'center',
|
||||
justifyContent: 'flex-start'
|
||||
}
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: 'Mixlab.share.ShareToWeibo',
|
||||
async beforeRegisterNodeDef (nodeType, nodeData, app) {
|
||||
if (nodeType.comfyClass == 'ShareToWeibo') {
|
||||
const orig_nodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
orig_nodeCreated?.apply(this, arguments)
|
||||
// console.log(this)
|
||||
const widget = {
|
||||
type: 'div',
|
||||
name: 'ShareToWeiboBtn',
|
||||
draw (ctx, node, widget_width, y, widget_height) {
|
||||
Object.assign(
|
||||
this.div.style,
|
||||
get_position_style(
|
||||
ctx,
|
||||
widget_width,
|
||||
node.widgets[2].last_y +16,
|
||||
node.size[1]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const style = `
|
||||
flex-direction: row;
|
||||
background-color: var(--comfy-input-bg);
|
||||
border-radius: 8px;
|
||||
border-color: var(--border-color);
|
||||
border-style: solid;
|
||||
color: var(--descrip-text);`
|
||||
|
||||
widget.div = $el('div', {})
|
||||
|
||||
const btn = document.createElement('button')
|
||||
btn.innerText = 'Share'
|
||||
btn.style = style
|
||||
|
||||
btn.addEventListener('click', () => {
|
||||
if (window._mixlab_share_to_weibo)
|
||||
window.open(window._mixlab_share_to_weibo)
|
||||
})
|
||||
|
||||
document.body.appendChild(widget.div)
|
||||
widget.div.appendChild(btn)
|
||||
|
||||
this.addCustomWidget(widget)
|
||||
|
||||
const onRemoved = this.onRemoved
|
||||
this.onRemoved = () => {
|
||||
widget.div.remove()
|
||||
return onRemoved?.()
|
||||
}
|
||||
|
||||
this.serialize_widgets = true //需要保存参数
|
||||
}
|
||||
|
||||
const onExecuted = nodeType.prototype.onExecuted
|
||||
nodeType.prototype.onExecuted = async function (message) {
|
||||
onExecuted?.apply(this, arguments)
|
||||
// console.log(this.widgets)
|
||||
|
||||
window._mixlab_share_to_weibo = message.url
|
||||
try {
|
||||
const div = this.widgets.filter(w => w.div)[0].div
|
||||
Array.from(
|
||||
div.querySelectorAll('button'),
|
||||
b => (b.style.background = 'yellow')
|
||||
)
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user