当前位置:AIGC资讯 > AIGC > 正文

有道ai写作,突破免费限制,无限制使用

预览效果

文末提供源码包及apk下载地址

有道ai写作python版

import hashlib
import time
import json
import ssl
import base64
import uuid

from urllib.parse import quote
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from sseclient import SSEClient


# 生成唯一的用户id
yduuid=str(uuid.uuid4()).replace('-','')

session = requests.session()
lastModified = requests.get('https://fanyi.youdao.com/index.html').headers['last-Modified']
_nlmf = int(time.mktime(time.strptime(lastModified, "%a, %d %b %Y %H:%M:%S GMT")))
session.headers = {
    'Referer': 'https://fanyi.youdao.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
}
session.get(f'https://rlogs.youdao.com/rlog.php?_npid=fanyiweb&_ncat=pageview&_ncoo=935962676.0432019&_nssn=NULL&_nver=1.2.0&_ntms={time.time()}&_nref=&_nurl=https%3A%2F%2Ffanyi.youdao.com%2Findex.html%23%2F&_nres=1920x1080&_nlmf={_nlmf}&_njve=0&_nchr=utf-8&_nfrg=%2F&/=NULL&screen=1920*1080')

# 获取md5加密结果
def get_md5(s,is_hex=True):
    md5=hashlib.md5()
    md5.update(s.encode())
    if is_hex:
      return md5.hexdigest()
    return md5.digest()

# AES-128-CBC解密
def decrypt(encrypted_data, key, iv):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted_data = cipher.decrypt(base64.b64decode(encrypted_data))
    return decrypted_data.decode('utf-8')


def get_token_and_key():
    params = {
        'product': 'webdict', 
        'appVersion': '1.0', 
        'client': 'web', 
        'mid': '1', 
        'vendor': 'web',
        'screen': '1', 
        'model': '1', 
        'imei': '1',
        'network': 'wired', 
        'keyfrom': 'webdict',
        'keyid': 'ai-write',
        'mysticTime': str(int(time.time()*1000)),
        'yduuid': yduuid,
    }
    # 参数排序
    sorted_params = sorted(params.items(), key=lambda x: x[0])
    sorted_params.append(("key","xuiC95RuooxC8Q51UJtdod1plLUhdAmt"))

    encoded_params = '&'.join([f"{key}={value}" for key, value in sorted_params])
    print("encoded_params:::::"+encoded_params)
    # 获取sign签名
    sign=get_md5(encoded_params)
    params.update({"sign":sign})
    params.update({"pointParam":"appVersion,client,imei,keyfrom,keyid,mid,model,mysticTime,network,product,screen,vendor,yduuid,key"})

    response = session.get('https://luna-ai.youdao.com/write/ai/web/ktf', params=params, verify=False)
    print(response.text)

    #============解密数据===============================
    e=response.text.replace("-","+").replace("_","/")
    key=get_md5("IIS0fzL@zGv1^zO2%NcZiTcM=98WYxdun$CJE1KUKFfEhz&zpEC0fdXfvGqy*N!r",is_hex=False)
    iv=get_md5("kG_oSxAXx#xjbiOKAkf9915Ko-XclOBP-GSgfo6E9ZB%9WvgcY6Y7dmje!+m5g#d",is_hex=False)

    s=decrypt(e,key,iv).replace('\x02', '')
    print("解密数据::::"+s)
    decode_data=json.loads(json.loads(s))
    return decode_data


def get_result(query):
    decode_data=get_token_and_key()
    params = {
        'product': 'webdict', 
        'appVersion': '1.0', 
        'client': 'web', 
        'mid': '1', 
        'vendor': 'web',
        'screen': '1', 
        'model': '1', 
        'imei': '1',
        'network': 'wired', 
        'keyfrom': 'webdict',
        'keyid': 'ai-write-web',
        'mysticTime': str(int(time.time()*1000)),
        'yduuid': yduuid,
        'functionId':'1',
        'query':quote(query),
        'userCustomize':quote(query),
        'token':decode_data["token"]
    }

    # 参数排序
    sorted_params = sorted(params.items(), key=lambda x: x[0])
    sorted_params.append(("key",decode_data['sk']))

    encoded_params = '&'.join([f"{key}={value}" for key, value in sorted_params])
    print("encoded_params:::::"+encoded_params)
    # 获取签名字符串
    sign=get_md5(encoded_params)
    params.update({"sign":sign})
    print("签名字符串:"+sign)
    params.update({"pointParam":"appVersion,client,functionId,imei,keyfrom,keyid,mid,model,mysticTime,network,product,query,screen,token,userCustomize,vendor,yduuid,key"})

    # 数据为multipart/form-data格式
    multipart_data = MultipartEncoder(fields=params)
    # 修改请求头中的Content-Type
    session.headers['Content-Type']= multipart_data.content_type
    # 发送请求
    response = session.post('https://luna-ai.youdao.com/write/ai/template/sse', data=multipart_data, stream=True,verify=False)

    # 处理SSE流数据
    client=SSEClient(response)
    for event in client.events():
        # 判断事件类型
        if event.event=='message':
            # 不换行输出
            print(json.loads(event.data)['content'],end='')


if __name__=='__main__':
    keyword=input('请输入关键词:')
    get_result(keyword)

有道ai写作lua版

使用Aide lua打包为apk

主要lua代码
require "import"
--import "androidx"
--import "androidx.appcompat.app.*"
--import "androidx.appcompat.view.*"
--import "androidx.appcompat.widget.*"
--import "android.app.*"
import "android.os.*"
import "android.widget.*"
import "android.view.*"
import "androidx.coordinatorlayout.widget.CoordinatorLayout"

local layout={
  CoordinatorLayout;
  layout_height="fill";
  layout_width="match_parent";
  {
    LinearLayout;
    layout_width="match_parent";
    orientation="vertical";
    layout_height="match_parent";
    {
      LinearLayout;
      layout_width="match_parent";
      orientation="horizontal";
      layout_height="wrap_content";
      {
        EditText;
        layout_marginTop="10";
        id="inputText";
        hint="请输入关键词";
        layout_weight=19;
        layout_marginLeft="5";
      };
      {
        Button;
        layout_marginTop="10";
        id="translateBtn";
        text="ai写作";
        layout_weight=1;
        layout_marginRight="5";
      };
    };
    {
      LinearLayout;
      layout_width="fill";
      layout_height="fill";
      {
        ScrollView;
        layout_width="fill";
        id="1";
        layout_height="fill";
        {
          TextView;
          layout_margin="10";
          layout_width="fill";
          id="resultView";
          layout_height="wrap_content";
        };
      };
    };
  };
};

--ui结束

activity.setContentView(loadlayout(layout))


-- 生成时间戳
function getTimestamp()
  local Date = luajava.bindClass "java.util.Date"
  return Date().getTime()
end

-- 字符串url编码
function urlEncode(s)
  -- url编码
  local s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end)
  -- 逗号不编码
  return s:gsub(" ", "+"):gsub("%%2C",","):gsub("%%25","%%")
end


-- 字符串序列化
function tableToStr(tbl,sep)
  local str = ''
  local sep= sep or '&'
  for key, value in pairs(tbl) do
    str = str .. key .. '=' .. urlEncode(value) .. sep
  end
  return string.sub(str, 1, -2)
end

-- 拼接排序后的表为字符串
function tableToStr1(tbl)
  local str = ''
  for key, value in ipairs(tbl) do
    str = str .. value[1] .. '=' .. urlEncode(value[2]) .. '&'
  end
  return string.sub(str, 1, -2)
end

-- md5加密
function md5Encrypt(data,isHex)
  local MessageDigest = luajava.bindClass "java.security.MessageDigest"
  local md = MessageDigest.getInstance("MD5")
  local bytes = md.digest(String(data).getBytes())
  local isHex= (isHex==nil) and true or false
  if isHex ==false then
    return bytes
  end
  local result = ""
  for i = 0, #bytes - 1 do
    local temp = string.format("%02x", (bytes[i] & 0xff))
    result = result .. temp
  end
  return result
end

-- AES解密
function decrypt(encryptStr, key, iv)
  local String = luajava.bindClass "java.lang.String"
  local SecretKeySpec = luajava.bindClass "javax.crypto.spec.SecretKeySpec"
  local IvParameterSpec = luajava.bindClass "javax.crypto.spec.IvParameterSpec"
  local Cipher = luajava.bindClass "javax.crypto.Cipher"
  local Base64 = luajava.bindClass "android.util.Base64"
  local algorithm = "AES"
  local mode = "AES/CBC/PKCS5Padding"
  local raw=SecretKeySpec(key,algorithm)
  local ivBytes = IvParameterSpec(iv)
  local cipher = Cipher.getInstance(mode)
  cipher.init(Cipher.DECRYPT_MODE, raw, ivBytes)
  local encode_content = Base64.decode(encryptStr, Base64.DEFAULT)
  local byte_content = cipher.doFinal(encode_content)
  return String(byte_content, "utf-8")
end

-- 公共请求参数定义
local base = {
  Cookies = {
    ['OUTFOX_SEARCH_USER_ID_NCOO'] = '1536815481.8081024',
    ['OUTFOX_SEARCH_USER_ID'] = '1773118125@192.168.0.1',
  },
  Headers = {
    ['Accept'] = 'application/json, text/plain, */*',
    ['Accept-Language'] = 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    ['Connection'] = 'keep-alive',
    ['Origin'] = 'https://fanyi.youdao.com',
    ['Referer'] = 'https://fanyi.youdao.com/',
    ['Sec-Fetch-Dest'] = 'empty',
    ['Sec-Fetch-Mode'] = 'cors',
    ['Sec-Fetch-Site'] = 'same-site',
    ['User-Agent'] =
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
    ['sec-ch-ua'] = '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',
    ['sec-ch-ua-mobile'] = '?0',
    ['sec-ch-ua-platform'] = '"Windows"',
  },
  Params = {
    ['product'] = 'webdict',
    ['appVersion'] = '1.0',
    ['client'] = 'web',
    ['mid'] = '1',
    ['vendor'] = 'web',
    ['screen'] = '1',
    ['model'] = '1',
    ['imei'] = '1',
    ['network'] = 'wired',
    ['keyfrom'] = 'webdict',
    ['keyid'] = 'ai-write',
    ['mysticTime'] = '',
    ['yduuid'] = '',
  }
}

-- 生成全局唯一用户id,同一id只有10次免费机会,每次生成不同id即可跳过免费限制
function genUUID()
  local UUID=luajava.bindClass 'java.util.UUID'
  return string.gsub(tostring(UUID.randomUUID()),'-','')
end


--复制表
function copyTable(original)
    local copy = {}
    for key, value in pairs(original) do
        if type(value) == "table" then
            copy[key] = copyTable(value) -- 递归复制子表
        else
            copy[key] = value
        end
    end
    return copy
end

-- 获得按键排序后的参数table
function getSortedParams(params)
  local function compare(a, b)
    return a[1] < b[1]
  end
  local sorted_params = {}
  for key, value in pairs(params) do
    table.insert(sorted_params, { key, value })
  end
  table.sort(sorted_params, compare)
  return sorted_params
end

-- 获取token和key
function getTokenAndKey()
  local JSON=require 'cjson'
  local url = 'https://luna-ai.youdao.com/write/ai/web/ktf'
  -- 复制公共表头和参数
  local headers = copyTable(base.Headers)
  local params = copyTable(base.Params)
  local cookies = tableToStr(base.Cookies,";")

  -- 设置参数
  params['mysticTime']=getTimestamp()
  -- 生成yduuid
  base.yduuid=genUUID()
  params['yduuid']=base.yduuid

  -- 按照table中键进行排序,并指定排序函数
  local sorted_params=getSortedParams(params)
  local encoded_params = tableToStr1(sorted_params)
  encoded_params = encoded_params .. "&key=xuiC95RuooxC8Q51UJtdod1plLUhdAmt"
  
  print("获取签名字符串"..encoded_params)

  local sign = md5Encrypt(encoded_params)
  print("获取签名的sign:"..sign)
  params['sign'] = sign
  params['pointParam'] =
  "appVersion,client,imei,keyfrom,keyid,mid,model,mysticTime,network,product,screen,vendor,yduuid,key"

  local finalUrl=url..'?'..tableToStr(params)
  print("请求地址"..finalUrl)
  -- 发送请求
  local httpTask=Http.get(finalUrl,cookies,nil,headers,function () end)
  local result=httpTask.get()
  local code,content,cookie,header=result[0],result[1],result[2],result[3]

  -- 解密数据
  local b64str=content:gsub(' ','+'):gsub('-','+'):gsub('_','/')

  -- des解密
  local key=md5Encrypt('IIS0fzL@zGv1^zO2%NcZiTcM=98WYxdun$CJE1KUKFfEhz&zpEC0fdXfvGqy*N!r',false)
  local iv=md5Encrypt('kG_oSxAXx#xjbiOKAkf9915Ko-XclOBP-GSgfo6E9ZB%9WvgcY6Y7dmje!+m5g#d',false)
  local s=tostring(decrypt(b64str,key,iv))
  s=string.gsub(s,'\x02','')
  print("token和sign"..s)
  local decodeData=JSON.decode(JSON.decode(s))
  return decodeData['sk'],decodeData['token']
end


-- 获取翻译结果
function getResult(query)
  local JSON=require 'cjson'
  local url = 'https://luna-ai.youdao.com/write/ai/template/sse'
  -- 复制公共表头和参数
  local headers = copyTable(base.Headers)
  local params = copyTable(base.Params)
  
  -- 获取token和key
  local key,token=getTokenAndKey()
  -- 设置参数
  params['mysticTime']=getTimestamp()
  params['yduuid']=base.yduuid
  params['keyid']='ai-write-web'
  params['functionId']='1'
  params['query']=urlEncode(query)
  params['userCustomize']=urlEncode(query)
  params['token']=token

  -- 设置头部
  local boundary="jeb3u3g5vh5v3hh2h2hg5g6v7vh4hehdjd"
  headers['Content-Type']='multipart/form-data;boundary='..boundary
  headers['Accept']='*/*, text/event-stream'
  headers["Referer"]="https://fanyi.youdao.com/aiwrite/document"

  -- 按照table中键进行排序,并指定排序函数
  local sorted_params=getSortedParams(params)
  local encoded_params=tableToStr1(sorted_params)

  encoded_params = encoded_params .. "&key="..key
  print('生成签名的参数字符串:::'..encoded_params)
  local sign = md5Encrypt(encoded_params)
  params['sign'] = sign
  print("签名结果:::"..sign)
  params['pointParam'] = 'appVersion,client,functionId,imei,keyfrom,keyid,mid,model,mysticTime,network,product,query,screen,token,userCustomize,vendor,yduuid,key'


  -- 处理sse事件流数据
  local OkHttpClient=luajava.bindClass 'okhttp3.OkHttpClient'
  local MultipartBody=luajava.bindClass 'okhttp3.MultipartBody'
  local Request=luajava.bindClass 'okhttp3.Request'
  local RealEventSource=luajava.bindClass 'okhttp3.internal.sse.RealEventSource'
  local EventSource=luajava.bindClass 'okhttp3.sse.EventSource'
  local EventSourceListener=luajava.bindClass 'okhttp3.sse.EventSourceListener'
  local TimeUnit=luajava.bindClass 'java.util.concurrent.TimeUnit'


  local client =OkHttpClient.Builder().connectTimeout(20,TimeUnit.SECONDS).readTimeout(20,TimeUnit.SECONDS).build()
  local requestBodyBuilder=MultipartBody.Builder().setType(MultipartBody.FORM)
  --添加请求参数
  for k,v in pairs(params) do
    requestBodyBuilder.addFormDataPart(String(k),String(tostring(v)))
  end
  local requestBody=requestBodyBuilder.build()

  local requestBuilder = Request.Builder().url(url)
  -- 添加请求头
  for k,v in pairs(headers) do
    requestBuilder.header(String(k),String(tostring(v)))
  end

  local request=requestBuilder.post(requestBody).build()
  -- 事件监听器
  local listener=EventSourceListener({
    onOpen=function(eventSource,response)
      print("建立sse链接")
      print(response)
    end,
    onEvent=function(eventSource,id,_type,data)
      -- 判断事件类型
      if _type=="message" then
        -- 更新ui
        activity.runOnUiThread(Runnable{
          run=function()
            local result=JSON.decode(data)
            resultView.append(result["content"])
          end
        })

      end
    end,
    onFailure=function(eventSource,t,response)
      print("打开链接失败")
    end,
    onClose=function(eventSource)
      print("连接关闭")
    end
  })

  local eventSource=RealEventSource(request,listener)
  --开启事件源连接
  eventSource.connect(client)
end


-- 测试
translateBtn.onClick=function()
  -- 清空上一次的结果
  resultView.setText("")
  local inputStr=tostring(inputText.getText())
  getResult(inputStr)
end

apk源码包及apk下载地址

源码:https://www.123pan.com/s/J5Nsjv-6XBN.html 提取码:SnKW apk:https://www.123pan.com/s/J5Nsjv-6XBN.html 提取码:SnKW

更新时间 2024-02-19