【AI JUST AI】Stable Disffusion | 配合Chrome插件,与Notion API完美联动

【AI JUST AI】Stable Disffusion | 配合Chrome插件,与Notion API完美联动

  • 第一步、Stable Diffusion 链接 CMS
    • 开发Chrome插件
      • 在合适的位置增加一个`发送至Notion`的按钮
      • 编写按钮的逻辑部分
    • 使用GitHub作为图床
      • 图片上传 API
  • 第二步,使用Chat GPT优化样式

Stable Diffusion是一个扩散模型,最早由德国CompVis发表并推出相关程式。后来AUTOMATIC1111开发了图形化界面:【stable diffusion web ui】,成为最多人使用的版本。下面简称SD WebUI。

简单来说,SD WebUI是能用AI技术绘图的开源软件,只要給定一組描述文字,AI就会画图出来;亦能模仿現有的图片,画出另一張图片。甚至給它一部分涂黑的圖片,AI也能按照你的意愿將图片填上适当的內容。除此之外还支援自行訓練模型加強绘制效果。

与其他的AI绘图软件相比,SD最大的优势在于:

  • 可以免费在自己的服务器上跑,只要遵照Creative ML OpenRAIL-M授权条款,就可以无限次使用。

其中,SD WebUI支持Linux、Windows、MacOS系统,以及Nvidia/AMD/Apple Silicon M的GPU。其图形界面可通过局域网IP进行网页访问的,上手无难度,还有社群制作的中文界面。
不过需要注意的时,AI绘图十分吃GPU性能,以Windows系统为例,建议电脑操作系统在Windows10以上,需配置独立显卡为Nvidia GTX1050 Ti (VRAM 4GB)以上等級,RAM大于8GB。
但是Stable Diffusion生成的图像只能保存在本地,并没有一键保存到云端的功能,如果需要保存在云端,我还需要再从本地文件夹中将图片上传到云端。
且我们都生成了这么多美丽的图片,却没有一个系统的内容管理,俗称CMS(Content management system),如果我们进行了一个系统的内容管理,那我们可以看到他的效果如下:
在这里插入图片描述
你可以把它作为你的作品集。

如果我们将这个内容管理系统扩散开来,成为一个社区,所造成的影响巨大。任何人都可以简单方便地在本地将自己的内容分享到CMS中,AI By The People,AI For The People。

第一步、Stable Diffusion 链接 CMS

想要实现想要的效果,我们首先得先对原有的WebUI界面进行改造:

增加一个按钮,当我们点击它时,会将我们生成好的图片以及相关的参数上传对应的CMS中。

我们将使用Chrome插件对WebUI进行改造(后续可能会考虑直接进行Stable Diffusion WebUI的扩展开发),使用Notion作为我们的CMS(Notion作为CMS具有易用、灵活、协作和跨平台等优势,特别是其Database功能,不仅让你白嫖免费v数据库,而且界面美观,让你可以更加高效地管理你的内容)。

Chrome谷歌浏览器开发文档
Chrome谷歌浏览器开发文档

在这里插入图片描述
Notion官网
话不多说,我们直接开始进入正题!

开发Chrome插件

首先,我们利用Chrome插件在我们的Stable Diffusion WebUI页面中选择一个合适的位置插入一个“发送到Notion”的按钮,如下图所示:
在这里插入图片描述

在合适的位置增加一个发送至Notion的按钮

  1. 要实现这个效果,我们首先需要编写manifest.json

    • 设置插件的基本信息
    • 只在127.0.0.1:7860(Stable Diffusion WebUI默认地址)上运行
    • 设置插件的权限

    代码如下:

    {
      "manifest_version": 2, // 浏览器扩展清单文件的版本号,2 表示使用 Manifest V2 版本
      "name": "Stable Diffusion To Notion", // 扩展程序的名称
      "version": "1.0", // 扩展程序的版本号
      "description": "将网页中的特定信息发送给Notion", // 扩展程序的描述
      "content_scripts": [ // 注册要注入到浏览器当前页面的脚本
        {
          "matches": [ // 注入的条件,数组里面的 URL 与当前页面 URL 匹配
            "http://127.0.0.1:7860/*" // 要注入的页面 URL,这里匹配了所有以 http://127.0.0.1:7860/ 开头的 URL
          ],
          "js": [ // 注入的 JavaScript 文件,这里只有一个 content.js
            "content.js"
          ]
        }
      ],
    	"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", // 安全策略
      "background": { // 后台脚本
        "scripts": [ // 执行的脚本文件,这里只有一个 background.js
          "background.js"
        ],
        "persistent": false // 是否常驻后台,false 表示不常驻
      },
      "browser_action": { // 扩展程序的浏览器操作区域,即点击图标后显示的弹出框
        "default_popup": "popup.html" // 弹出框所需的 HTML 文件
      },
      "permissions": [ // 扩展程序需要的权限
        "http://127.0.0.1:7860/", // 可以访问的 URL
        "activeTab", // 可以获取当前激活的标签页的信息
        "tabs", // 可以获取所有标签页的信息
        "storage", // 可以使用浏览器存储 API
        "https://api.notion.com/*" // 可以访问 Notion API 的 URL
        "https://api.github.com/*" // 可以访问 GitHub API 的 URL
      ]
    }
    

    需要注意的是:

    您在 manifest.json 中添加了 content_security_policy 配置,该配置指定了扩展的内容安全策略。

    默认情况下,Chrome 扩展的内容脚本会在一个沙箱环境中运行,以防止不受信任的代码在扩展环境中执行,并且默认情况下不允许使用 eval() 等动态代码执行函数,以防止脚本注入攻击。 然而,在某些情况下,这可能会阻止一些正常的脚本行为。

    在您的情况下,您的 background.js 文件尝试使用 chrome.runtime.sendMessage() 函数与您的 content.js 文件进行通信,但是由于默认的内容安全策略阻止了 eval() 函数的使用,因此该函数无法正常运行。 通过添加 content_security_policy 配置并将 script-src 指定为 'unsafe-eval',您允许了动态代码执行函数的使用,因此 chrome.runtime.sendMessage() 函数能够正常运行。

    需要注意的是,虽然在某些情况下禁用默认的内容安全策略可能是必要的,但这可能会导致您的扩展面临更大的安全风险。在使用 content_security_policy 配置时,请确保您仅允许必要的资源,并避免允许来自不受信任的源的代码执行。

    本回答由Chat GPT生成

  2. 编写background.js代码:

    • 后台监控
    • content.js注入到页面中
    • 监听来自content.js的消息

    代码如下:

    // 当插件安装时,输出一条信息到控制台
    chrome.runtime.onInstalled.addListener(function () {
      console.log("Extension installed");
    });
    
    // 监听标签页更新事件
    chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
      // 如果当前标签页的 URL 以 http://127.0.0.1:7860/ 开头且加载完成
      if (tab && tab.url && changeInfo.status == "complete" && tab.url.indexOf("http://127.0.0.1:7860/") == 0) {
        // 在当前标签页中注入 content.js 脚本
        chrome.tabs.executeScript(tabId, { file: "content.js" });
        console.log("插入content.js");
      } else {
        console.log("未插入content.js");
      }
    });
    
  3. 编写conten.js代码:

    • 从页面中获取需要发送的信息(这里主要指的是图片以及图片相关的参数)

    • 按钮插入至Stable Diffusion WebUI中合适位置,并获取Web中的同类型的ClassName,并套用在嵌入的按钮元素上

      获取页面元素位置:
      在这里插入图片描述
      右键,复制其JS路径,即:document.querySelector("body > gradio-app").shadowRoot.querySelector("#image_buttons_txt2img")
      在这里插入图片描述
      复制同类型的样式
      在这里插入图片描述
      代码如下:

      // 监听加载完毕的事件
      window.addEventListener("load", function () {
          console.log("页面加载完毕,延时1s后开始插入button")
          // 创建一个按钮元素
          const button = document.createElement("button");
          // 延迟 1 秒钟执行按钮插入操作(等待页面加载完毕)
          setTimeout(function () {
              button.innerHTML = "发送到 Notion";
              // 获取Web中的同类型的ClassName,并套用在嵌入的按钮元素上
              button.className = "gr-button gr-button-lg gr-button-secondary";
              //增加元素的title
              button.setAttribute("title", "将图像写入Notion");
      
              // 将按钮添加到页面中的特定位置
              const container = document.querySelector("body > gradio-app").shadowRoot.querySelector("#component-229")
              if (container) {
                  container.appendChild(button);
                  console.log("已经将button插入指定位置");
              } else {
                  console.log("未找到容器元素,将按钮添加到页面底部");
                  // 将按钮添加到页面底部
      						document.body.appendChild(button);
              }
          }, 1000);
      });
      

      至此,我们就可以实现将“发送至Notion”按钮嵌入到Stable Diffusion WebUI中的效果了!
      在这里插入图片描述

编写按钮的逻辑部分

外观效果有了,接下来,让我们来实现点击按钮的逻辑部分,即点击按钮后,我们生成好的图片以及相关的参数都会上传至Notion对应的数据库中

  1. 继续编写content.js代码

    • 增加获取页面数据的方法-getInfoFromPage(),获取包括img、prompt、negativePrompt和parameter信息

    代码如下:

    // 从页面中获取需要发送的信息
    function getInfoFromPage() {
        // 在这里编写代码来获取信息
        console.log("执行getInfoFromPage")
        const img = document.querySelector("body > gradio-app").shadowRoot.querySelector("#txt2img_gallery > div.overflow-y-auto.h-full.p-2.min-h-\\[350px\\].max-h-\\[55vh\\].xl\\:min-h-\\[450px\\] > div > button > img")
        console.log(img)
        const all_msg = document.querySelector("body > gradio-app").shadowRoot.querySelector("#html_info_txt2img > p");
    
        let all_msg_str = all_msg.textContent.trim();
        console.log(all_msg_str);
    
        // 匹配需要的信息,包括prompt、negativePrompt和parameter
        const regex = /^(?:([^<\n]*)(?:\nNegative prompt: ([^<\n]*))?)?\n(.+)$/m;
        const match = all_msg_str.match(regex);
        console.log(match);
    
        let prompt = '';
        let negativePrompt = '';
        let parameter = '';
        if (match) {
            if (match[1].includes("Negative prompt: ")) {
                prompt = '';
                negativePrompt = match[1] || '';
                parameter = match[3] || '';
            } else {
                prompt = match[1] || '';
                negativePrompt = match[2] || '';
                parameter = match[3] || '';
            }
            console.log(prompt);
            console.log(negativePrompt);
            console.log(parameter);
        } else {
            console.log('No match found.');
        }
    
        // 返回需要发送的信息
        return {
            "img": img.src,
            "prompt": prompt,
            "negativePrompt": negativePrompt,
            "parameter": parameter
        }
    }
    
    1. 继续编写content.js代码
    • 添加按钮点击事件的监听器,放在按钮创建完成之后
    • 向后台脚本发送消息,指示其打开popup.html界面,并将getInfoFromPage()中的信息传递给它

    代码如下:

    // 延迟 1 秒钟执行按钮插入操作(等待页面加载完毕)
    setTimeout(function () {
        // 创建一个按钮元素
        const button = document.createElement("button");
        button.innerHTML = "发送到 Notion";
        // 获取Web中的同类型的ClassName,并套用在嵌入的按钮元素上
        button.className = "gr-button gr-button-lg gr-button-secondary";
        //增加元素的title
        button.setAttribute("title", "将图像写入Notion");
        // 将按钮添加到页面中的特定位置
        const container = document.querySelector("body > gradio-app").shadowRoot.querySelector("#component-229")
    
        if (container) {
            container.appendChild(button);
            console.log("已经将button插入指定位置");
        } else {
            console.log("未找到容器元素,将按钮添加到页面底部");
            // 将按钮添加到页面底部
            document.body.appendChild(button);
        }
        // 添加按钮点击事件的监听器
        button.addEventListener("click", function () {
            // 从页面中获取需要发送的信息
            const info = getInfoFromPage();
            console.log(info)
            // 向后台脚本发送一个消息,指示它打开popup.html并将信息传递给它
            chrome.runtime.sendMessage({ action: "open_popup", info: info }, function (response) {
                console.log(response);
            });
        });
    }, 1000);
    
    1. 编写background.js代码
    • 监听来自content.js的消息
    • 将信息传递给popup.html界面

    代码如下:

    // 监听来自content.js的消息
    chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
      // 如果请求是打开popup.html并传递信息
      if (request.action === "open_popup") {
        // 创建一个新的窗口,打开popup.html
        chrome.windows.create({
          url: chrome.extension.getURL("popup.html"),
          type: "popup",
          width: 600,
          height: 400
        }, function (window) {
          // 在窗口加载完成后向它发送一个消息,将信息传递给它
          chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
            if (changeInfo.status === "complete") {
              chrome.tabs.sendMessage(tabId, { info: request.info }, function (response) {
                console.log(response);
              });
            }
          });
        });
      }
    });
    
    1. 编写popup.html界面
    • 设置基本样式,主要包含:确定发送至Notion - sendToNotion按钮,展示从页面中获取的数据

    代码如下:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8" />
        <title>Stable Diffusion To Notion</title>
    
        <!-- 样式定义 -->
        <style>
            body {
                width: 400px;
                height: 400px;
            }
    
            #info {
                overflow: auto;
                height: 300px;
            }
        </style>
        <!-- 加载脚本文件 -->
        <script src="popup.js"></script>
    </head>
    
    <body>
        <!-- 标题 -->
        <h1>请确认以下信息发送到Notion?</h1>
        <!-- 发送到 Notion 按钮 -->
        <button id="sendToNotion">确定</button>
        <!-- 从页面中获取的信息 -->
        <h3>从页面中获取的信息:</h3>
        <div id="info_img">img</div>
        <div id="info_prompt">Prompt</div>
        <div id="info_negativePrompt">Negative Prompt</div>
        <div id="info_parameter">Parameter</div>
    </body>
    
    </html>
    
    1. 编写popup.js代码
      在第3步,我们在background.js中编写了一个监听事件,当popup.html加载完毕时,会将获取到的Stable Diffusion WebUI的页面数据info发送给popup.js,因此我们这里需要编写一个监听事件监听数据接收,并将接收的数据渲染到popup.html界面中
    • 编写send2Notion(info)方法,将popup.html渲染好的数据(包括img、prompt、negativePrompt和parameter)发送至Notion

      关于Notion API的详细使用,我们要学会看官方文档
      在这里插入图片描述
      在这里插入图片描述
      监听sendToNotion按钮点击事件,当sendToNotion按钮被点击时,获取信息并调用将信息发送至Notion方法 - send2Notion(info)
      代码如下:

      document.addEventListener('DOMContentLoaded', function () {
          console.log('Hello, world!');
      
          // 监听发送到 Notion 按钮的点击事件
          document.getElementById('sendToNotion').addEventListener('click', function () {
              // 获取信息
              const info = {
                  negativePrompt: document.getElementById('info_negativePrompt').textContent,
                  parameter: document.getElementById('info_parameter').textContent,
                  prompt: document.getElementById('info_prompt').textContent,
              };
              console.log(info);
              // 发送信息到 Notion
              send2Notion(info);
          });
      
          // 监听来自 background.js 的消息
          chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
              console.log(request);
              if (request.info) {
                  // 找到要渲染的元素
                  var info_img = document.getElementById("info_img");
                  var info_negativePrompt = document.getElementById("info_negativePrompt");
                  var info_parameter = document.getElementById("info_parameter");
                  var info_prompt = document.getElementById("info_prompt");
                  // 将接收到的信息渲染到该元素中
                  info_img.textContent = request.info.img;
                  info_negativePrompt.textContent = request.info.negativePrompt;
                  info_parameter.textContent = request.info.parameter;
                  info_prompt.textContent = request.info.prompt;
                  sendResponse("message received");
              }
          });
      });
      
      async function send2Notion(info) {
          console.log("data", info);
          let notion_api_key = "你的Notion API Key"
          let databaseID = "你的数据库ID"
      
          // 发送 POST 请求到 Notion API
          let dataResponse = await fetch('https://api.notion.com/v1/pages', {
              method: 'POST',
              headers: {
                  'Authorization': 'Bearer ' + notion_api_key,
                  'Notion-Version': '2022-06-28',
                  'Content-Type': 'application/json'
              },
              referrerPolicy: "no-referrer-when-downgrade",
              mode: "same-origin",
              body: JSON.stringify({
                  "parent": { "database_id": databaseID },
                  "properties": {
                      "Name": {
                          "title": [
                              {
                                  "text": {
                                      "content": "Detail"
                                  }
                              }
                          ]
                      },
                      "Prompt": {
                          "rich_text": [
                              {
                                  "text": {
                                      "content": info.prompt
                                  }
                              }
                          ]
                      },
                      "Negative Prompt": {
                          "rich_text": [
                              {
                                  "text": {
                                      "content": info.negativePrompt
                                  }
                              }
                          ]
                      },
                      "Parameter": {
                          "rich_text": [
                              {
                                  "text": {
                                      "content": info.parameter
                                  }
                              }
                          ]
                      }
                  }
              })
          }).then(response => response.json());
      
         if (dataResponse) {
              // 显示弹窗
              alert("信息已成功发送至 Notion!");
              // 关闭 popup.html 窗口
              window.close();
          } else {
              // 发生错误,打印错误信息
              console.log("发送信息至 Notion 时发生错误:", dataResponse);
          }
      }
      

      至此,本地的Stable Diffusion WebUI已经可以通过上传至Notion按钮与Notion对应的数据库链接,这里给大家看一下实际效果:
      在这里插入图片描述
      在这里插入图片描述

接下来我们再来看看数据库这边,
在这里插入图片描述

可以看到,数据确实添加进去了,但是没有图片!
原因很明显,我们没有上传图片,而且也Notion也不支持从外部上传图片到其数据库中,其只支持从外部链接读取文件(图片)。
在这里插入图片描述
因此我们需要使用外部的文件托管服务(图床),这里我们使用Github为我提供文件托管服务。

使用GitHub作为图床

关于如何使用GitHub API上传文件以及用GitHub做图床,可以参考这篇:
『转载』使用GitHub API上传文件及GitHub做图床 – 邱少羽梦

基于 Github API 的图床 Chrome 插件开发全纪录 - 掘金

图片上传 API

图片上传使用了 content API 的 create-a-file 接口,通过 PUT 发送一条文件内容为 base64 的请求到指定的仓库目录
在这里插入图片描述
这里着重圈出了必须把文件进行 base64 编码,否则接口调用将会出错。

在传输数据时,如果使用二进制方式传输,数据传输过程中可能会出现乱码或者数据丢失的问题,而Base64编码能够将二进制数据转换成ASCII字符,不会出现这样的问题,同时也能够减小数据大小,减小传输量。所以在调用API接口时,将图片转换为base64编码是常见手段。

如果是更新文件,需要先获取待更新文件的sha
在这里插入图片描述
更新文件的sha可以通过直接Get请求拿到,如下:
在这里插入图片描述
在这里插入图片描述
然后再切换成PUT,附带参数发送过去即可
在这里插入图片描述
使用APIPost7调试

在搭好图床以及了解好GitHub API后,我们要明确我们的业务需求:

  • 选择图片和把图片转化成 base64
  • 将图片的base64上传至GitHub

现在我们来开始搭建实现我们的业务需求:

  1. 选择图片和把图片转化成base64

    这里我们首先使用在popup.html上编写相应的图片展示
    在这里插入图片描述
    代码如下:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8" />
        <title>Stable Diffusion To Notion</title>
    
        <style>
            body {
                width: 400px;
                height: 400px;
            }
    
            #info {
                overflow: auto;
                height: 300px;
            }
        </style>
        <script src="popup.js"></script>
    </head>
    
    <body>
        <h1>请确认以下信息发送到Notion?</h1>
        <button id="sendToNotion">确定</button>
        <h3>从页面中获取的信息:</h3>
        <img id="info_img" />
        <div id="info_prompt">Prompt</div>
        <div id="info_negativePrompt">Negative Prompt</div>
        <div id="info_parameter">Parameter</div>
    </body>
    
    </html>
    

    然后在popup.js中编写代码获取其img元素,接着就是对这个img进行base64转换的操作

如何把文件进行base64编码?
可以使用 JavaScript 中的 btoa() 方法将 “hello world” 转换为 Base64 编码。 btoa() 方法将字符串转换为 Base64 编码字符串。

以下是一个将 “hello world” 转换为 Base64 的示例代码:

const str = "hello world";
const base64 = btoa(str);
console.log(base64); // 输出 "aGVsbG8gd29ybGQ="

在此示例中,str 是要转换的字符串,base64 是转换后的 Base64 编码字符串。您可以使用 console.log() 输出 base64

在我们的示例中,您也可以通过创建一个Image对象并将其设置为在popup.html中定义的img元素来获取图片数据并将其转换为base64编码。

以下是一个将图片文转换为 Base64 编码字符串的示例代码:

// 将图片解码至base64
let img2Notion_url = ""
function translate() {
    // 创建一个Promise对象
    return new Promise((resolve, reject) => {
        // 获取页面中的图片元素
        const img = document.getElementById('info_img');
        // 创建一个新的Image对象
        const image = new Image();
        // 设置Image对象的src属性为图片元素的src属性
        image.src = img.src;
        // 分割图片src属性的字符串并获取图片的名称
        const splitArray = image.src.split("/");
        const img_name = splitArray[splitArray.length - 2] + "/" + splitArray[splitArray.length - 1];
        console.log(img_name);
        // 构建图片在GitHub上的url地址
        img2Notion_url = "https://github.com/Mr-KID-github/Stable-Diffusion-Open-Community/blob/main/images/" + img_name + "?raw=true"
        // 当图片加载完成后执行回调函数
        image.onload = function () {
            // 创建一个canvas元素并设置其宽度和高度为图片的宽度和高度
            const canvas = document.createElement('canvas');
            canvas.width = image.width;
            canvas.height = image.height;
            // 获取canvas的2D绘图上下文对象
            const context = canvas.getContext('2d');
            // 在canvas上绘制图片
            context.drawImage(image, 0, 0);
            // 将canvas内容转换为base64格式的字符串
            const base64 = canvas.toDataURL().split(',')[1];

            console.log(base64);
            // 将解码后的base64格式的图片和图片名称通过resolve方法返回给调用方
            resolve({
                data: base64,
                name: img_name
            });
        };
    });
}

同时,这里需要注意一个细节点,导入Notion中链接格式应该为如下格式:

https://github.com/Mr-KID-github/Stable-Diffusion-Open-Community/blob/main/images/" + img_name + "?raw=true"

本回答由Chat GPT辅助生成

  1. 在我们将图片base64编码后,即可尝试图片上传Github操作了

    同样,我们这次用APIPost测试,如图所示即是成功:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2Y8iNBV-1680334527356)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1945d287-17e1-4277-825c-441dbcf43c2f/Untitled.png)]

    接着,我们就可以开始编写我们的将图片文件上传到 GitHub 仓库中方法了,代码如下:

    // 定义一个异步函数,用于将图片文件上传到 GitHub 仓库中
    async function uploadFileToGithub() {
        // 将图片解码至 base64 格式
        const imgbase64 = await translate();
        console.log(imgbase64.data);
        // 构造上传图片所需的 GitHub API 请求 URL
        const Github_url = "https://api.github.com/repos/Mr-KID-github/Stable-Diffusion-Open-Community/contents/images/" + imgbase64.name;
    
        // 发送 PUT 请求将图片文件上传到 GitHub 仓库
        return window.fetch(Github_url, {
            method: 'PUT',
            headers: {
                "Accept": "application/vnd.github+json ",
                "Content-Type": "application/json",
                "X-GitHub-Api-Version": "2022-11-28",
                "Authorization": "Bearer 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"
            },
            body: JSON.stringify({
                "message": "Stable Diffusion 上传图片 " + imgbase64.name,
                "content": imgbase64.data
            })
        })
            // 处理上传结果
            .then(async res => {
                if (res.status >= 200 && res.status < 400) {
                    // 如果上传成功,返回成功信息和响应内容
                    return {
                        status: res.status,
                        data: await res.json()
                    }
                } else {
                    // 如果上传失败,弹出提示框,并返回失败信息和响应内容
                    alert("图片上传GitHub图床失败!");
                    console.log(res);
                    return {
                        status: res.status,
                        data: null
                    }
                }
            })
            // 捕捉可能的异常
            .catch(e => e);
    }
    
  2. 在send2Notion方法中增加Github图床中的对应图片链接

    ......
    let dataResponse = await fetch('https://api.notion.com/v1/pages', {
            method: 'POST',
            headers: {
                'Authorization': 'Bearer ' + notion_api_key,
                'Notion-Version': '2022-06-28',
                'Content-Type': 'application/json'
            },
            referrerPolicy: "no-referrer-when-downgrade",
            mode: "same-origin",
            body: JSON.stringify({
                "parent": { "database_id": databaseID },
                "properties": {
                    "Name": {
                        "title": [
                            {
                                "text": {
                                    "content": "Detail"
                                }
                            }
                        ]
                    },
                    "Prompt": {
                        "rich_text": [
                            {
                                "text": {
                                    "content": info.prompt
                                }
                            }
                        ]
                    },
                    "Negative Prompt": {
                        "rich_text": [
                            {
                                "text": {
                                    "content": info.negativePrompt
                                }
                            }
                        ]
                    },
                    "Parameter": {
                        "rich_text": [
                            {
                                "text": {
                                    "content": info.parameter
                                }
                            }
                        ]
                    }
                },
                "children": [
                    {
                        "object": "block",
                        "type": "image",
                        "image": {
                            "type": "external",
                            "external": {
                                "url": img2Notion_url
                            }
                        }
                    },
                ]
            })
        })
    ......
    

第二步,使用Chat GPT优化样式

如图所示:
在这里插入图片描述
最后确定的样式如下:
在这里插入图片描述
至此,我们的工作就全部完成啦!你上传的所有图片都会在这个平台展示出来:

Stable Diffusion Open Community
在这里插入图片描述

当然,你也可以在这个平台看到所有人开源出来的图片以及相关的提词!

所有源代码全部放置Github开源平台!如果喜欢的话请点击Star,让更多人关注到我们,一起加入光荣的进化吧!

https://github.com/Mr-KID-github/Stable-Diffusion-Open-Community


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/6213.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

超详细WindowsJDK1.8与JDK11版本切换教程

文章目录一、JDK生效原理二、安装配置JDK11三、切换JDK11版本四、查看切换JDK11版本是否成功五、再次切换至JDK8版本六、查看切换JDK8版本是否成功一、JDK生效原理 想必大家都在为如何流畅的切换JDK版本问题而来&#xff0c;那么在此篇文章开始之前&#xff0c;首先我们来思考一…

网络传输层

目录传输层再谈端口号端口号范围划分认识知名端口号netstatpidofUDP协议UDP协议端格式UDP的特点面向数据报UDP的缓冲区UDP使用注意事项使用udp协议 的应用层协议其它TCP协议TCP协议段格式如何理解链接如何理解三次握手如何理解四次挥手概念TIME_WAIT/CLOSE_WAITTCP策略确认应答…

【wps】【毕业论文】三线表的绘制

目录 一、三线表 二、制作步骤 &#xff08;1&#xff09;点击“插入”——点击“表格”创建一个表格 &#xff08;2&#xff09;选中整个表格——鼠标右键选择“边框和底纹”&#xff0c;“表格属性”再点击“边框和底纹”——点击“自定义”——选择表格的边的宽度——如图…

北京筑龙智能寻源 |助力企业一站式智能采购,降本增效

智能寻源——精准匹配&#xff0c;让采购更高效 智能寻源系统是北京筑龙为采购人搭建的一款全链路高效协同的采购寻源和供应商管理平台。助力采购人快速完成采购计划&#xff0c;提升采购效率&#xff0c;降低采购风险。 基于智能寻源系统&#xff0c;将全面打通供应商数据壁…

VR数字政务,VR全景技术,探索数字化治理新路径

近年来&#xff0c;随着虚拟现实&#xff08;VR&#xff09;技术的不断发展&#xff0c;VR数字政务也逐渐成为行政数字化转型的重要组成部分。VR数字政务可以为行政部门提供全新的数字化解决方案&#xff0c;使行政部门的工作更加高效、便捷和安全。 一、VR数字政务的定义和概述…

ABBYY FineReader PDF15下载安装教程

刚刚&#xff0c;老板给我一堆扫描文件&#xff08;图片和pdf文件&#xff09;&#xff0c;拿不到源文件&#xff0c;让我把客户发的扫描文件搞成word文档&#xff0c;密密麻麻&#xff0c;这些文件100多页&#xff0c;这要手工敲能把手敲费。 这时候&#xff0c;让我想到了这…

小白的git入门教程(三)

书接上文&#xff0c;我们讲到如何进行版本日志回退&#xff0c;根据这个&#xff0c;我们可以返回到任意状态 今天让我们接着讲完git的基本指令操作教程以及其余分支 删除文件操作 前提&#xff1a;要被删除的文件已经存储在本地库中 这里我们可以创建一个文件&#xff08;待…

ActiViz.NET 9.2.2023 Crack

适用于 .Net C# 和 Unity 的 3D 可视化库 释放可视化工具包的强大功能&#xff0c;在 C#、.Net 和 Unity 软件中为您的 3D 内容服务。 ActiViz 允许您轻松地将 3D 可视化集成到您的应用程序中。 Kitware 围绕 ActiViz 和 3D 应用程序提供支持和自定义开发 活动可视化功能 C…

【Java代码审计】表达式注入

1 前置知识 1.1 EL表达式 EL表达式主要功能&#xff1a; 获取数据&#xff1a;可以从JSP四大作用域中获取数据执行运算&#xff1a;执行一些关系运算&#xff0c;逻辑运算&#xff0c;算术运算获取web开发常用对象&#xff1a;通过内置 的11个隐式对象获取想要的数据调用jav…

STL容器之initializer_list与set

STL容器之initializer_list与setinitializer_list案例二&#xff08;实现n个数的加法&#xff09;set单集合有序性唯一性删除元素多重集合less与greater自定义类型initializer_list initializer_list创建的对象&#xff0c;初始值可以有很多个&#xff0c;像vector 一样 想多少…

第05章_排序与分页

第05章_排序与分页 &#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前在…

SPI、I2C、CAN通信的简单介绍和笔记

标题中的三种通信方式&#xff08;协议&#xff09;是比较常见的一些通信协议&#xff0c;对于它们有一定的了解对于我们学习嵌入式单片机的学习有着非常重要的作用。于是我们对此有一些信息给到各位读者&#xff0c;这也是笔者自己巩固知识点的方式。如果觉得有帮到各位&#…

551、Elasticsearch详细入门教程系列 -【分布式全文搜索引擎 Elasticsearch(二)】 2023.04.04

目录一、Elasticsearch创建/查看/删除索引、创建/查看/修改/删除文档、映射关系1.1 Elasticsearch中的数据格式1.2 索引操作1.2.1 创建索引1.2.2 查看指定索引1.2.3 查看全部索引1.2.4 删除索引1.3 文档操作1.3.1 创建文档1.3.2 查看单个文档&#xff1a;主键查询1.3.3 查看所有…

不敲代码用ChatGPT开发一个App

先说下背景&#xff0c;有一天我在想 ChatGPT 对于成熟的开发者来说已经是一个非常靠谱的助手了&#xff0c;身边也确实有很多同事把它作为一个离不开的助理担当。 但是如果我只是略微懂一点前端知识的新人&#xff0c;了解 HTML、CSS、JS 相关的知识&#xff0c;想开发一个安…

什么是UEFI签名认证?UEFI签名有什么好处?

为了防御恶意软件攻击&#xff0c;目前市面上所有电脑设备启动时默认开启安全启动(Secure Boot)模式。安全启动(Secure Boot)是UEFI扩展协议定义的安全标准&#xff0c;可以确保设备只使用OEM厂商信任的软件启动。UEFI签名认证就是对运行在 UEFI 系统下的 efi 驱动和通过 UEFI …

第10章_创建和管理表

第10章_创建和管理表 &#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前…

OpenCloudOS 9.0发布,腾讯闯入底层基础软件“深水区”

3月22日&#xff0c;腾讯发布了2022第四季度及全年业绩&#xff0c;ToB业务成为腾讯的核心引擎。与此同时&#xff0c;ToB的腾讯在近年来持续加码自研投入&#xff0c;提升底层技术实力&#xff0c;2022年研发投入达到614亿元&#xff0c;2018年至今在研发上的投入已经超过2056…

Mockito单测之道

Mockito单测之道 去年写过一篇《TestNG单元测试实战》文章&#xff0c;严格来讲算集成测试。 没看的小伙伴可直接看本篇即可&#xff0c;本质是单元测试框架不同&#xff0c;写法不一样。 单测定义 单元测试定义&#xff1a; 对软件中最小可测单元进行验证&#xff0c;可理解…

【数据结构】链表练习题(2)

链表练习题1.相交链表(LeetCode160)2.环形链表(LeetCode141)3.环形链表Ⅱ(LeetCode142)1.相交链表(LeetCode160) 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。题目数据 保…

spring注解的使用

Spring的一个核心功能是IOC&#xff0c;就是将Bean初始化加载到容器中&#xff0c;Bean是如何加载到容器的&#xff0c;可以使用Spring注解方式或者Spring XML配置方式。 Spring注解方式减少了配置文件内容&#xff0c;更加便于管理&#xff0c;并且使用注解可以大大提高了开发…