Commit fcf1d19f by 庄欣

第一次提交

parents
## 项目说明
### mp-downloader
chrome插件项目,用于米拍官方网站作品详情页的下载工具
### nginx-ext
使用openrsty开发的在nginx层面拦截验证发送短信请求有效性的代码
\ No newline at end of file
{
"manifest_version": 2,
"name": "mepai-downloader",
"description": "米拍下图工具",
"version": "1.0",
"permissions": [
"tabs"
],
"content_scripts": [
{
"matches": ["https://www.mepai.me/works/*", "https://www.photosaas.cn/*"],
"css": ["static/css/main.css"],
"js": ["static/js/jquery.min.js","static/js/index.js"],
"run_at": "document_end"
}
],
"web_accessible_resources": [
"ui.html"
],
"browser_action": {
"default_icon": "static/icon.png",
"default_title": "米拍下载小工具",
"default_popup": "popup.html"
}
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
width:100px;
}
</style>
</head>
<body>
<div>米拍downloader</div>
<div>v0.0.1</div>
</body>
<script src="./static/js/background.js"></script>
</html>
\ No newline at end of file
.mpDonloaderParentDom {
height: 50px;
width: 100px;
border-radius: 10px;
background-color: #fffccc;
position: fixed;
top: 0;
left: calc(100vw - 500px);
display: flex;
align-content: center;
justify-content: center;
color: brown;
z-index: 998;
cursor: pointer;
align-items: center;
}
.downloaderUi {
position: fixed;
width: 1080px;
height: 610px;
z-index: 999;
}
.__container {
width: 500px;
height: 700px;
overflow: scroll;
position: fixed;
top:20px;
left:20px;
z-index: 999;
background: #ffffff;
}
.__container .hidden {
display: none;
}
.__container .images {
display: flex;
flex-wrap: wrap;
}
.__container .images .item {
width: 30%;
margin-left: 3%;
margin-top: 10px;
}
.__container .images .item img {
width: 100%;
height: 100%;
}
.__container .mark {
position: relative;
height: 20px;
margin-top:-20px;
opacity: 0.6;
z-index: 100;
width: 100%;
background: #000000;
color: #fffccc;
display: flex;
justify-content: space-between;
}
.__container .mark input {
-webkit-appearance: checkbox!important;
}
.__container .buttons {
display: flex;
margin-top: 10px;
justify-content: center;
margin-bottom: 40px;
}
.__container .buttons .button {
width: 100px;
border-radius: 10px;
margin-right: 20px;
background: #FF9F2A;
text-align: center;
color: #ffffcc;
cursor: hand;
}
.__container .focus {
box-shadow: 2px 2px 10px #FF9F2A;
}
\ No newline at end of file
chrome.tabs.getSelected(null, function(tab) {
console.log("asdfasdfasdfasdf");
console.log(tab);
chrome.tabs.sendRequest(tab.id, {url: tab.url}, function(response) {
console.log(response);
});
});
\ No newline at end of file
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
console.log("网页端");
console.log(request);
});
var urlCircle = [];
setInterval(function () {
let currentUrl = window.location.href;
if (urlCircle.length > 0 && urlCircle.shift() !== currentUrl) {
init();
}
urlCircle.push(currentUrl)
}, 1000);
var body = $("#__nuxt");
var parentDom = $(document.createElement("div"));
var img = new Image();
var selectedList = [];
var checkedProp = false;
img.src = chrome.extension.getURL("ui.html");
parentDom.addClass("mpDonloaderParentDom");
parentDom.html("打开下载窗口");
parentDom.click(function() {
toggleButton();
});
body.append(parentDom);
var UI = chrome.extension.getURL("ui.html");
var isOpen = false;
var container = null;
var index = getIndex();
function init() {
if (isOpen) {
selectedList = [];
isOpen = false;
toggleButton();
}
}
bindChangeImg();
bindChangeWorkEvents();
function openUi() {
var isFrist = true;
$.get(UI, (html) => {
container = $(html);
let tpl = container.find("#tpl")[0].outerHTML;
let images = getImages();
var doms = [];
for(var i in images) {
if (isNaN(i)) {
break;
}
var _ = $(tpl);
$($(_).find("img")[0]).attr("src" , images[i].url + "!340w.jpg");
if (isFrist) {
$($(_).find("img")[0]).addClass("focus");
}
isFrist = false;
$($(_).children().find("input[type=checkbox]")[0]).val(images[i].url);
$($(_).children().find("input[type=checkbox]")[0]).attr("fileid", images[i].name);
$($(_).find(".fileid")[0]).text(images[i].name);
doms.push(_.html());
};
$(container.find(".images")[0]).html(doms.join(""));
$.each(container.find(".item"), (i,n) => {
$(n).find("img")[0].onclick = () => {
setSelect($(n).find("img")[0], images);
};
});
$.each(container.find(".item"), (i,n) => {
$(n).find("img")[0].onclick = () => {
setSelect($(n).find("img")[0], images);
};
});
$(container).find(".selectAll")[0].onclick=function() {
selectAll();
};
$(container).find(".startDownload")[0].onclick=function() {
downloadAll();
};
body.append(container);
});
}
function closeUi() {
if (container !== null) {
$(container).remove();
}
}
function refreshIndex() {
index = getIndex();
}
function toggleButton() {
closeUi();
if (isOpen === false) {
openUi();
}
isOpen = !isOpen;
}
function setSelect(dom, all) {
let src = dom.src.split("!")[0];
let big = $(".swiper-slide-active").find("img")[0].src.split("!")[0];
let images = [];
let direction = "";
$.each(all, (i,n) => {
images.push(n.url);
});
let index1 = images.indexOf(src);
let index2 = images.indexOf(big);
if (index1 < index2) {
direction = ".btn-prev"
}
if (index1 > index2) {
direction = ".btn-next"
}
if ($.trim(direction) !== "") {
for (var i = 0;i<Math.abs(index1-index2);i++) {
$(direction).click();
}
}
}
function getImages() {
var id = "";
var lists = [];
var images = [];
var reg = /\/\d{1,}\//g;
var records = [];
lists = $(".swiper-wrapper").find("img");
var urls = [];
var imgSrc = "";
$.each(lists, (i,n) => {
urls = n.currentSrc.split("!");
imgSrc = urls[0];
if (imgSrc.indexOf("videos.mepai.me") < 0) {
if (records.indexOf(imgSrc) < 0) {
if (id === "") {
var idStrings = imgSrc.match(reg);
if (idStrings.length > 0) {
id = idStrings[0].replace(/\//g, "");
}
}
records.push(imgSrc);
images.push({
name: id + "-" + index(),
url: imgSrc
});
}
}
});
refreshIndex();
return images;
}
function selectAll() {
checkedProp = !checkedProp;
$($(body).find("input[type='checkbox']")).attr("checked", checkedProp);
}
function getCurrentImg() {
var src = $("div.swiper-slide-active").find("img")[0].src;
var urls = src.split("!");
if (urls.length > 1) {
return urls[0];
}
return src;
}
function changeFocus() {
setTimeout(() => {
var currentUrl = getCurrentImg();
if (container == null) {
return;
}
$($(container).find("img")).removeClass("focus");
var imgs = $(container).find("img");
for(var i in imgs) {
if (imgs[i].src === currentUrl + "!340w.jpg") {
$(imgs[i]).addClass("focus")
break;
}
}
}, 500);
}
function downloadAll() {
if (confirm("点击确定开始下载!")) {
$.each($(body).find("input[type='checkbox']:checked"), (i,n) => {
downloadResource($(n).val(), $(n).attr("fileid"));
});
}
}
function downloadResource(url, name){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
// get binary data as a response
var blob = this.response;
const url = window.URL.createObjectURL(blob);
var link = document.createElement('a');
link.href= url;
var filename = name + ".jpg";
link.setAttribute('download', filename);
evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, true);
link.dispatchEvent(evt);
}
};
xhr.send();
}
function getIndex() {
var index = 1;
return function() {
return index ++;
}
}
function bindChangeWorkEvents() {
return false;
}
function bindChangeImg() {
$(".btn-next").click(()=>{
changeFocus();
})
$(".btn-prev").click(()=>{
changeFocus();
})
}
\ No newline at end of file
<style>
</style>
<div class="__container">
<div class="hidden" id="tpl">
<div class="item">
<img src="" />
<div class="mark">
<div><input type="checkbox" fileid=""/></div>
<div><label class="fileId"></label></div>
</div>
</div>
</div>
<div class="images">
</div>
<div class="buttons" style="">
<div class="button selectAll">
全选
</div>
<div class="button startDownload">
下载
</div>
</div>
</div>
version: "3"
services:
nginx:
image: nginx:1.18.0
ports:
- 80:80
volumes:
- ./test.conf:/etc/nginx/nginx.conf
content_by_lua_block {
if ngx.req.get_method() == ngx.HTTP_GET then
local uri = ngx.var.uri;
local params = ngx.req.get_uri_args();
ngx.log(ngx.ERR, "进入逻辑")
local headers = ngx.req.get_headers();
local version = headers["app-version"];
local device = headers["app-device"];
ngx.log(ngx.ERR, "device:" .. device)
if version == nil or device == nil then
ngx.exit(ngx.HTTP_UNAUTHORIZED);
end
device = string.lower(device);
local sign = params["sign"];
local t = params["t"];
if device == "android" or device == "ios" then
local encodedSign = ngx.md5(device .. t .. version);
if encodedSign ~= sign then
ngx.log(ngx.ERR, "luaMd5的结果" .. encodedSign)
ngx.log(ngx.ERR, "客户端的sign:" .. sign)
ngx.exit(ngx.HTTP_UNAUTHORIZED);
end
end
if device == "www" or device == "m" then
local apiSecretId = "AKIDoN4nLkxNQcR5YttVjmdT7czC4f8PgeVG"
local apiSecretKey = "mE6oLySlIfsysaI5pNuGRZWOXbUFqFkQ"
local appId ="2030055684"
local secretKey = "03sufjIZDGoItxXBvnx_4Ag"
local ticket = params["ticket"];
local randomStr = params["randomStr"];
local ip = ngx.var.remote_addr;
local data = {
"Action=DescribeCaptchaResult",
"AppSecretKey=" .. secretKey,
"CaptchaAppId=" .. appId,
"CaptchaType=9",
"Nonce=".. random(1000, 9000),
"Randstr=".. randomStr,
"SecretId=" .. apiSecretId
"Ticket="..ticket,
"Timestamp=" .. ngx.time(),
"UserIp=".. ip,
"Version=2019-07-22",
}
local str = "";
for value in data do
if (postData ~= "") then
str = str .. "&" .. value
else
str = value
end
end
local waitToEncoded = "GETcaptcha.tencentcloudapi.com/?" .. str;
local encodeStr = ngx.encode_base64(ngx.hmac_sha1(apiSecretKey, waitToEncoded));
data["Signature"] = encodeStr;
local finalStr = "";
for value in data do
if finalStr ~= "" then
finalStr = finalStr .. "&" .. value
else
finalStr = value
end
end
local t = ngx.location.capture("https://captcha.tencentcloudapi.com/?" .. finalStr)
ngx.log(ngx.ERR,"从腾讯出来的结果" .. t)
ngx.log(ngx.ERR, "客户端ticket:" .. ticket)
if t.Response.CaptchaCode ~= 1 then
ngx.exit(ngx.HTTP_UNAUTHORIZED);
end
end
end
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment