├── pages ├── home │ ├── home.json │ ├── home.wxml │ ├── home.wxss │ └── home.js ├── remove │ ├── remove.json │ ├── remove.wxml │ ├── remove.wxss │ └── remove.js ├── me │ ├── me.json │ ├── me.wxml │ ├── me.js │ └── me.wxss ├── about │ ├── about.json │ ├── about.wxml │ ├── about.wxss │ └── about.js └── logs │ ├── logs.json │ ├── logs.wxss │ ├── logs.wxml │ └── logs.js ├── code.jpg ├── images ├── arrow.png ├── clear.png ├── avatar.png ├── douyin.png ├── huoshan.png ├── kuaishou.png ├── me-init.png ├── meipai.png ├── pipixia.png ├── weishi.png ├── home-init.png ├── me-active.png ├── me-banner.png └── home-active.png ├── sitemap.json ├── README.md ├── app.wxss ├── .gitignore ├── utils ├── util.js └── md5.js ├── project.config.json ├── app.json └── app.js /pages/home/home.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /pages/remove/remove.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /pages/me/me.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "个人中心" 3 | } -------------------------------------------------------------------------------- /pages/about/about.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "关于我们" 3 | } -------------------------------------------------------------------------------- /pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志" 3 | } -------------------------------------------------------------------------------- /code.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/code.jpg -------------------------------------------------------------------------------- /images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/arrow.png -------------------------------------------------------------------------------- /images/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/clear.png -------------------------------------------------------------------------------- /images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/avatar.png -------------------------------------------------------------------------------- /images/douyin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/douyin.png -------------------------------------------------------------------------------- /images/huoshan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/huoshan.png -------------------------------------------------------------------------------- /images/kuaishou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/kuaishou.png -------------------------------------------------------------------------------- /images/me-init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/me-init.png -------------------------------------------------------------------------------- /images/meipai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/meipai.png -------------------------------------------------------------------------------- /images/pipixia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/pipixia.png -------------------------------------------------------------------------------- /images/weishi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/weishi.png -------------------------------------------------------------------------------- /images/home-init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/home-init.png -------------------------------------------------------------------------------- /images/me-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/me-active.png -------------------------------------------------------------------------------- /images/me-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/me-banner.png -------------------------------------------------------------------------------- /images/home-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/home-active.png -------------------------------------------------------------------------------- /pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /pages/about/about.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 免费提供抖音视频、快手视频、皮皮虾视频、微视视频、火山视频、美拍视频去水印服务。 4 | -------------------------------------------------------------------------------- /sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /pages/about/about.wxss: -------------------------------------------------------------------------------- 1 | /* pages/about/about.wxss */ 2 | Page { 3 | background: #f4f4f4; 4 | } 5 | 6 | .container { 7 | padding: 50rpx 32rpx; 8 | } 9 | 10 | .container .about { 11 | font-size: 32rpx; 12 | color: #333; 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # remove-code 2 | 3 | #### 项目介绍 4 | 5 | 去水印小程序 6 | 7 | > 抖音的有点不稳定,有需要的自行更换接口;appid 自行配置 8 | 9 | #### 邮箱 10 | 11 | yidierh@gmail.com 12 | 13 | ![小程序二维码](https://raw.githubusercontent.com/eddieyd/remove-code/master/code.jpg) 14 | -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 200rpx 0; 9 | box-sizing: border-box; 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/unit/coverage/ 8 | /test/e2e/reports/ 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | const util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | logs: [] 7 | }, 8 | onLoad: function () { 9 | this.setData({ 10 | logs: (wx.getStorageSync('logs') || []).map(log => { 11 | return util.formatTime(new Date(log)) 12 | }) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | const formatTime = date => { 2 | const year = date.getFullYear() 3 | const month = date.getMonth() + 1 4 | const day = date.getDate() 5 | const hour = date.getHours() 6 | const minute = date.getMinutes() 7 | const second = date.getSeconds() 8 | 9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 10 | } 11 | 12 | const formatNumber = n => { 13 | n = n.toString() 14 | return n[1] ? n : '0' + n 15 | } 16 | 17 | module.exports = { 18 | formatTime: formatTime 19 | } 20 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "miniprogram", 14 | "libVersion": "2.2.4", 15 | "appid": "", 16 | "projectname": "remove-code", 17 | "debugOptions": { 18 | "hidedInDevtools": [] 19 | }, 20 | "isGameTourist": false, 21 | "simulatorType": "wechat", 22 | "simulatorPluginLibVersion": {}, 23 | "condition": { 24 | "search": { 25 | "current": -1, 26 | "list": [] 27 | }, 28 | "conversation": { 29 | "current": -1, 30 | "list": [] 31 | }, 32 | "game": { 33 | "currentL": -1, 34 | "list": [] 35 | }, 36 | "miniprogram": { 37 | "current": -1, 38 | "list": [] 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /pages/home/home.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{item.text}} 7 | 8 | 9 | 10 | 11 | 12 | {{item.text}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /pages/about/about.js: -------------------------------------------------------------------------------- 1 | // pages/about/about.js 2 | Page({ 3 | 4 | /** 5 | * 页面的初始数据 6 | */ 7 | data: { 8 | 9 | }, 10 | 11 | /** 12 | * 生命周期函数--监听页面加载 13 | */ 14 | onLoad: function (options) { 15 | 16 | }, 17 | 18 | /** 19 | * 生命周期函数--监听页面初次渲染完成 20 | */ 21 | onReady: function () { 22 | 23 | }, 24 | 25 | /** 26 | * 生命周期函数--监听页面显示 27 | */ 28 | onShow: function () { 29 | 30 | }, 31 | 32 | /** 33 | * 生命周期函数--监听页面隐藏 34 | */ 35 | onHide: function () { 36 | 37 | }, 38 | 39 | /** 40 | * 生命周期函数--监听页面卸载 41 | */ 42 | onUnload: function () { 43 | 44 | }, 45 | 46 | /** 47 | * 页面相关事件处理函数--监听用户下拉动作 48 | */ 49 | onPullDownRefresh: function () { 50 | 51 | }, 52 | 53 | /** 54 | * 页面上拉触底事件的处理函数 55 | */ 56 | onReachBottom: function () { 57 | 58 | }, 59 | 60 | /** 61 | * 用户点击右上角分享 62 | */ 63 | onShareAppMessage: function () { 64 | 65 | } 66 | }) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/home/home", 4 | "pages/me/me", 5 | "pages/remove/remove", 6 | "pages/logs/logs", 7 | "pages/about/about" 8 | ], 9 | "window": { 10 | "backgroundTextStyle": "light", 11 | "navigationBarBackgroundColor": "#fff", 12 | "navigationBarTitleText": "短视频去水印大师免费版", 13 | "navigationBarTextStyle": "black" 14 | }, 15 | "tabBar": { 16 | "color": "#333", 17 | "selectedColor": "#ff5a44", 18 | "borderStyle": "black", 19 | "list": [ 20 | { 21 | "selectedIconPath": "images/home-active.png", 22 | "iconPath": "images/home-init.png", 23 | "pagePath": "pages/home/home", 24 | "text": "视频" 25 | }, 26 | { 27 | "selectedIconPath": "images/me-active.png", 28 | "iconPath": "images/me-init.png", 29 | "pagePath": "pages/me/me", 30 | "text": "我的" 31 | } 32 | ] 33 | }, 34 | "sitemapLocation": "sitemap.json" 35 | } -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | // 展示本地存储能力 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | 9 | // 登录 10 | wx.login({ 11 | success: res => { 12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 13 | } 14 | }) 15 | // 获取用户信息 16 | wx.getSetting({ 17 | success: res => { 18 | if (res.authSetting['scope.userInfo']) { 19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 20 | wx.getUserInfo({ 21 | success: res => { 22 | // 可以将 res 发送给后台解码出 unionId 23 | this.globalData.userInfo = res.userInfo 24 | 25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 26 | // 所以此处加入 callback 以防止这种情况 27 | if (this.userInfoReadyCallback) { 28 | this.userInfoReadyCallback(res) 29 | } 30 | } 31 | }) 32 | } 33 | } 34 | }) 35 | }, 36 | globalData: { 37 | userInfo: null 38 | } 39 | }) -------------------------------------------------------------------------------- /pages/me/me.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 用户名:{{userInfo.nickName}} 11 | 12 | 13 | 14 | 15 | 16 | 关于我们 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /pages/home/home.wxss: -------------------------------------------------------------------------------- 1 | /* pages/home/home.wxss */ 2 | 3 | Page { 4 | background: #f4f4f4; 5 | } 6 | 7 | .container { 8 | padding: 0 24rpx; 9 | } 10 | 11 | .container .home-items { 12 | display: inline-flex; 13 | margin-top: 32rpx; 14 | width: 100%; 15 | height: 146rpx; 16 | background: #fff; 17 | border-radius: 28rpx; 18 | box-shadow: 0 0 10rpx 0 19 | rgba(0, 0, 0, 0.1); 20 | justify-content: center; 21 | align-items: center; 22 | } 23 | 24 | .container .home-items__disable { 25 | opacity: .5; 26 | } 27 | 28 | .container .container-top { 29 | display: inline-flex; 30 | width: 100%; 31 | justify-content: space-around; 32 | } 33 | 34 | .container .container-top .home-items-first { 35 | display: flex; 36 | margin-top: 32rpx; 37 | flex-direction: column; 38 | align-items: center; 39 | justify-content: center; 40 | width: 329rpx; 41 | height: 290rpx; 42 | background: #fff; 43 | border-radius: 28rpx; 44 | box-shadow: 0 0 10rpx 0 45 | rgba(0, 0, 0, 0.1); 46 | box-sizing: border-box; 47 | } 48 | 49 | .container .container-top .home-items-first .items-img-first { 50 | width: 160rpx; 51 | height: 160rpx; 52 | } 53 | 54 | .container .container-top .home-items-first .items-text-first { 55 | margin-top: 16rpx; 56 | font-size: 30rpx; 57 | } 58 | 59 | .container .home-items .items-img { 60 | margin-right: 32rpx; 61 | width: 86rpx; 62 | height: 86rpx; 63 | } 64 | 65 | .container .home-items .items-text { 66 | font-size: 30rpx; 67 | } 68 | -------------------------------------------------------------------------------- /pages/remove/remove.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 请务必确认视频在APP中无水印,不然无法去掉水印 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 使用说明 26 | 1.复制您想要去除水印的短视频链接 27 | 2.把复制的链接粘贴在输入框中(可以包含文字) 28 | 3.点击获取视频即可获得无水印链接 29 | 30 | -------------------------------------------------------------------------------- /pages/home/home.js: -------------------------------------------------------------------------------- 1 | // pages/home/home.js 2 | Page({ 3 | 4 | /** 5 | * 页面的初始数据 6 | */ 7 | data: { 8 | homeData: [ 9 | { 10 | icon: '../../images/douyin.png', 11 | text: '抖音去水印', 12 | type: 'douyin' 13 | }, 14 | { 15 | icon: '../../images/weishi.png', 16 | text: '微视去水印', 17 | type: 'weishi' 18 | }, 19 | { 20 | icon: '../../images/huoshan.png', 21 | text: '火山去水印', 22 | type: 'huoshan' 23 | }, 24 | { 25 | icon: '../../images/kuaishou.png', 26 | text: '快手去水印', 27 | type: 'kuaishou' 28 | }, 29 | { 30 | icon: '../../images/meipai.png', 31 | text: '美拍去水印', 32 | type: 'meipai' 33 | }, 34 | { 35 | icon: '../../images/pipixia.png', 36 | text: '皮皮虾去水印', 37 | type: 'pipixia' 38 | } 39 | ] 40 | }, 41 | 42 | /** 43 | * 生命周期函数--监听页面加载 44 | */ 45 | onLoad: function (options) { 46 | 47 | }, 48 | 49 | /** 50 | * 生命周期函数--监听页面初次渲染完成 51 | */ 52 | onReady: function () { 53 | 54 | }, 55 | 56 | /** 57 | * 生命周期函数--监听页面显示 58 | */ 59 | onShow: function () { 60 | 61 | }, 62 | 63 | /** 64 | * 生命周期函数--监听页面隐藏 65 | */ 66 | onHide: function () { 67 | 68 | }, 69 | 70 | /** 71 | * 生命周期函数--监听页面卸载 72 | */ 73 | onUnload: function () { 74 | 75 | }, 76 | 77 | /** 78 | * 页面相关事件处理函数--监听用户下拉动作 79 | */ 80 | onPullDownRefresh: function () { 81 | 82 | }, 83 | 84 | /** 85 | * 页面上拉触底事件的处理函数 86 | */ 87 | onReachBottom: function () { 88 | 89 | }, 90 | 91 | /** 92 | * 用户点击右上角分享 93 | */ 94 | onShareAppMessage: function () { 95 | 96 | } 97 | }) -------------------------------------------------------------------------------- /pages/me/me.js: -------------------------------------------------------------------------------- 1 | // pages/me/me.js 2 | Page({ 3 | 4 | /** 5 | * 页面的初始数据 6 | */ 7 | data: { 8 | userInfo: '' 9 | }, 10 | getUserInfo: function(e) { 11 | let _this = this 12 | if (e.detail.errMsg === "getUserInfo:ok") { 13 | _this.setData({ 14 | 'userInfo': e.detail.userInfo 15 | }) 16 | } else { 17 | _this.showNeed() 18 | } 19 | }, 20 | 21 | /** 22 | * 请求授权 23 | */ 24 | showNeed: function() { 25 | wx.showToast({ 26 | title: '点击头像进行登录', 27 | icon: 'none' 28 | }) 29 | }, 30 | 31 | /** 32 | * 生命周期函数--监听页面加载 33 | */ 34 | onLoad: function(options) { 35 | let _this = this 36 | //查看是否授权 37 | wx.getSetting({ 38 | success: function(res) { 39 | if (res.authSetting['scope.userInfo']) { 40 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称 41 | wx.getUserInfo({ 42 | success: function(res) { 43 | _this.setData({ 44 | 'userInfo': res.userInfo 45 | }) 46 | } 47 | }) 48 | } else { 49 | _this.showNeed() 50 | } 51 | }, 52 | fail(res) { 53 | _this.showNeed() 54 | } 55 | }) 56 | }, 57 | 58 | /** 59 | * 生命周期函数--监听页面初次渲染完成 60 | */ 61 | onReady: function() { 62 | 63 | }, 64 | 65 | /** 66 | * 生命周期函数--监听页面显示 67 | */ 68 | onShow: function() { 69 | 70 | }, 71 | 72 | /** 73 | * 生命周期函数--监听页面隐藏 74 | */ 75 | onHide: function() { 76 | 77 | }, 78 | 79 | /** 80 | * 生命周期函数--监听页面卸载 81 | */ 82 | onUnload: function() { 83 | 84 | }, 85 | 86 | /** 87 | * 页面相关事件处理函数--监听用户下拉动作 88 | */ 89 | onPullDownRefresh: function() { 90 | 91 | }, 92 | 93 | /** 94 | * 页面上拉触底事件的处理函数 95 | */ 96 | onReachBottom: function() { 97 | 98 | }, 99 | 100 | /** 101 | * 用户点击右上角分享 102 | */ 103 | onShareAppMessage: function() { 104 | 105 | } 106 | }) -------------------------------------------------------------------------------- /pages/me/me.wxss: -------------------------------------------------------------------------------- 1 | /* pages/me/me.wxss */ 2 | Page { 3 | background: #f4f4f4; 4 | } 5 | 6 | .me-header { 7 | position: relative; 8 | width: 100%; 9 | height: 413rpx; 10 | } 11 | 12 | .me-userInfo { 13 | position: absolute; 14 | display: flex; 15 | top: 172rpx; 16 | left: 0; 17 | flex-direction: column; 18 | align-items: center; 19 | width: 100%; 20 | } 21 | 22 | .me-header-avatar { 23 | width: 164rpx; 24 | height: 164rpx; 25 | border-radius: 50%; 26 | border: 5rpx solid rgba(255, 255, 255, 0.8); 27 | background: #fff; 28 | } 29 | 30 | .me-header-avatar-btn { 31 | padding: 0; 32 | width: 164rpx; 33 | height: 164rpx; 34 | border-radius: 50%; 35 | border: 5rpx solid rgba(255, 255, 255, 0.8); 36 | } 37 | 38 | .me-header-avatar-btn::after { 39 | border: none; 40 | } 41 | 42 | .me-header-avatar-btn .btn-image { 43 | width: 164rpx; 44 | height: 164rpx; 45 | } 46 | 47 | .me-header-text { 48 | margin-top: 10rpx; 49 | font-size: 30rpx; 50 | text-align: center; 51 | } 52 | 53 | .me-header-text-btn { 54 | margin-top: 20rpx; 55 | font-size: 30rpx; 56 | line-height: 30rpx; 57 | background: #fff; 58 | } 59 | 60 | .me-header-text-btn::after { 61 | border: none; 62 | } 63 | 64 | .me-header-banner { 65 | width: 100%; 66 | height: 100%; 67 | } 68 | 69 | .me-navigator { 70 | position: relative; 71 | display: inline-flex; 72 | padding: 0 24rpx; 73 | margin-top: 20rpx; 74 | width: 100%; 75 | height: 93rpx; 76 | align-items: center; 77 | background: #fff; 78 | box-sizing: border-box; 79 | } 80 | 81 | .me-navigator .me-navigator-text { 82 | margin-left: 16rpx; 83 | font-size: 30rpx; 84 | color: #333; 85 | } 86 | 87 | .me-navigator .me-navigatior-arrow { 88 | position: absolute; 89 | right: 24rpx; 90 | width: 14rpx; 91 | height: 26rpx; 92 | z-index: 10; 93 | } 94 | 95 | .me-get-wrapper { 96 | margin-top: 16rpx; 97 | padding: 24rpx; 98 | } 99 | 100 | .me-get-wrapper .me-get { 101 | margin: auto; 102 | font-size: 30rpx; 103 | height: 82rpx; 104 | line-height: 82rpx; 105 | background: #ff5a44; 106 | color: #fff; 107 | border-radius: 15rpx; 108 | } 109 | 110 | .btn-contact-view{ 111 | width: 100%; 112 | position: fixed; 113 | bottom: 60rpx; 114 | } 115 | 116 | .btn-contact{ 117 | line-height: 80rpx; 118 | width: 300rpx; 119 | height: 80rpx; 120 | background: #ff5a44; 121 | color: #fff; 122 | font-size: 30rpx; 123 | border-radius: 70rpx; 124 | } 125 | -------------------------------------------------------------------------------- /pages/remove/remove.wxss: -------------------------------------------------------------------------------- 1 | /* pages/remove/remove.wxss */ 2 | 3 | .container { 4 | padding: 40rpx 75rpx; 5 | box-sizing: border-box; 6 | } 7 | 8 | .container .remove-img { 9 | width: 120rpx; 10 | height: 120rpx; 11 | } 12 | 13 | .container .remove-content { 14 | margin-top: 72rpx; 15 | width: 100%; 16 | } 17 | 18 | .container .remove-content .remove-tips { 19 | display: block; 20 | width: 100%; 21 | font-size: 24rpx; 22 | color: #ff5a44; 23 | text-align: center; 24 | } 25 | 26 | .container .remove-content .remove-input-wrapper { 27 | position: relative; 28 | } 29 | 30 | .container .remove-content .remove-input-wrapper .remove-input { 31 | margin-top: 16rpx; 32 | padding: 0 72rpx 0 24rpx; 33 | width: 100%; 34 | height: 74rpx; 35 | font-size: 30rpx; 36 | border: 2rpx solid #d4d4d4; 37 | border-radius: 15rpx; 38 | box-sizing: border-box; 39 | } 40 | 41 | .container .remove-content .remove-input-wrapper .remove-clear { 42 | position: absolute; 43 | top: 22rpx; 44 | right: 24rpx; 45 | width: 34rpx; 46 | height: 34rpx; 47 | } 48 | 49 | .container .remove-btn-danger { 50 | margin-top: 32rpx; 51 | font-size: 30rpx; 52 | height: 82rpx; 53 | line-height: 82rpx; 54 | background: #ff5a44; 55 | color: #fff; 56 | border-radius: 15rpx; 57 | } 58 | 59 | .container .remove-getContent { 60 | margin-top: 72rpx; 61 | width: 100%; 62 | text-align: center; 63 | } 64 | 65 | .container .remove-getContent .url-wrapper { 66 | font-size: 24rpx; 67 | color: #ff5a44; 68 | overflow: hidden; 69 | text-overflow: ellipsis; 70 | white-space: nowrap; 71 | } 72 | 73 | .container .remove-getContent .remove-vedio { 74 | width: 600rpx; 75 | height: 450rpx; 76 | } 77 | 78 | .container .remove-getContent .remove-btn-wrapper { 79 | margin-top: 32rpx; 80 | display: inline-flex; 81 | justify-content: center; 82 | } 83 | 84 | .container .remove-getContent .remove-btn-wrapper .remove-btn-primary { 85 | margin-left: 48rpx; 86 | background: #fff; 87 | height: 82rpx; 88 | line-height: 82rpx; 89 | color: #ff5a44; 90 | border: 2rpx solid #ff5a44; 91 | } 92 | 93 | .container .remove-getContent .remove-btn-wrapper .bottom { 94 | margin-top: 0; 95 | width: 276rpx; 96 | } 97 | 98 | .container .copy-tips { 99 | display: flex; 100 | flex-direction: column; 101 | margin-top: 148rpx; 102 | } 103 | 104 | .container .copy-tips .tips-title { 105 | font-size: 28rpx; 106 | text-align: center; 107 | color: #333; 108 | } 109 | 110 | .container .copy-tips .tips-text { 111 | margin-top: 32rpx; 112 | font-size: 26rpx; 113 | color: #333; 114 | } 115 | 116 | /* 进度条 */ 117 | progress { 118 | margin-top: 20rpx; 119 | } -------------------------------------------------------------------------------- /pages/remove/remove.js: -------------------------------------------------------------------------------- 1 | // pages/remove/remove.js 2 | const MD5 = require('../../utils/md5.js') 3 | 4 | Page({ 5 | 6 | /** 7 | * 页面的初始数据 8 | */ 9 | data: { 10 | type: '', 11 | placeholder: '', 12 | removeUrl: '', 13 | icon: '', 14 | vedioUrl: '', 15 | showCancel: false, 16 | percent: '', 17 | showProgress: false, 18 | downStart: false 19 | }, 20 | 21 | /** 22 | * 数据绑定 23 | */ 24 | removeUrl: function (e) { 25 | let _this = this 26 | let _removeUrl = e.detail.value 27 | if (_removeUrl) { 28 | _removeUrl = _this.formatUrl(_removeUrl) 29 | this.setData({ 30 | 'removeUrl': _removeUrl, 31 | 'showCancel': true 32 | }) 33 | } else { 34 | this.setData({ 35 | 'showCancel': false 36 | }) 37 | } 38 | }, 39 | 40 | /** 41 | * 生命周期函数--监听页面加载 42 | */ 43 | onLoad: function (options) { 44 | let _type = options.type 45 | let _typeName = '' 46 | let _icon = '' 47 | if (_type === 'douyin') { 48 | _typeName = '抖音' 49 | _icon = '../../images/douyin.png' 50 | } else if (_type === 'weishi') { 51 | _typeName = '微视' 52 | _icon = '../../images/weishi.png' 53 | } else if (_type === 'huoshan') { 54 | _typeName = '火山' 55 | _icon = '../../images/huoshan.png' 56 | } else if (_type === 'kuaishou') { 57 | _typeName = '快手' 58 | _icon = '../../images/kuaishou.png' 59 | } else if (_type === 'meipai') { 60 | _typeName = '美拍' 61 | _icon = '../../images/meipai.png' 62 | } else if (_type === 'pipixia') { 63 | _typeName = '皮皮虾' 64 | _icon = '../../images/pipixia.png' 65 | } 66 | this.setData({ 67 | type: options.type, 68 | placeholder: `请输入${_typeName}视频链接`, 69 | icon: _icon 70 | }) 71 | }, 72 | 73 | /** 74 | * 生命周期函数--监听页面初次渲染完成 75 | */ 76 | onReady: function () { 77 | this.confirmClip() 78 | }, 79 | 80 | /** 81 | * 生命周期函数--监听页面显示 82 | */ 83 | onShow: function () { 84 | 85 | }, 86 | 87 | /** 88 | * 生命周期函数--监听页面隐藏 89 | */ 90 | onHide: function () { 91 | 92 | }, 93 | 94 | /** 95 | * 生命周期函数--监听页面卸载 96 | */ 97 | onUnload: function () { 98 | 99 | }, 100 | 101 | /** 102 | * 页面相关事件处理函数--监听用户下拉动作 103 | */ 104 | onPullDownRefresh: function () { 105 | 106 | }, 107 | 108 | /** 109 | * 页面上拉触底事件的处理函数 110 | */ 111 | onReachBottom: function () { 112 | 113 | }, 114 | 115 | /** 116 | * 用户点击右上角分享 117 | */ 118 | onShareAppMessage: function () { 119 | 120 | }, 121 | 122 | /** 123 | * 获取视频 124 | */ 125 | getVedio: function (e) { 126 | if (e.detail.errMsg === "getUserInfo:ok") { 127 | let _this = this 128 | let _url = _this.data.removeUrl 129 | let _type = _this.data.type 130 | let oppen_id = '' 131 | if (_url) { 132 | if (_url.indexOf('rmapi.h5youx.com')>0) { 133 | wx.showToast({ 134 | title: '请输入正确的链接地址', 135 | icon: 'none' 136 | }) 137 | return false 138 | } else { 139 | let reg = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/ 140 | if (reg.test(_url)) { 141 | wx.showLoading({ 142 | title: '正在获取...', 143 | mask: true 144 | }) 145 | } else { 146 | wx.showToast({ 147 | title: '请输入正确的链接地址', 148 | icon: 'none' 149 | }) 150 | return false 151 | } 152 | } 153 | } else { 154 | wx.showToast({ 155 | title: '请输入视频链接地址', 156 | icon: 'none' 157 | }) 158 | return false 159 | } 160 | wx.request({ 161 | url: 'https://rmapi.h5youx.com/vlink/s.php', 162 | method: 'GET', 163 | dataType: 'JSON', 164 | data: { 165 | link: _url, 166 | type: _type, 167 | sign: MD5.hex_md5(_url + _type + 'xiaochengxv') 168 | }, 169 | success(res) { 170 | let _res = JSON.parse(res.data) 171 | if (_res.succ) { 172 | _this.setData({ 173 | vedioUrl: _res.data.video 174 | }) 175 | wx.hideLoading() 176 | } else { 177 | wx.hideLoading() 178 | wx.showToast({ 179 | title: _res.retDesc, 180 | icon: 'none' 181 | }) 182 | } 183 | }, 184 | fail(res) { 185 | wx.showToast({ 186 | title: '服务器繁忙', 187 | icon: 'none' 188 | }) 189 | } 190 | }) 191 | } 192 | }, 193 | 194 | /** 195 | * 保存视频 196 | */ 197 | saveVedio: function () { 198 | let _this = this 199 | wx.getSetting({ 200 | success: (res) => { 201 | if (!res.authSetting['scope.writePhotosAlbum']) { 202 | wx.authorize({ 203 | scope: 'scope.writePhotosAlbum', 204 | success() { 205 | _this.saveToAlbum() 206 | } 207 | }) 208 | } else { 209 | _this.saveToAlbum() 210 | } 211 | } 212 | }) 213 | }, 214 | 215 | /** 216 | * 保存视频到相册 217 | */ 218 | saveToAlbum: function () { 219 | let _vedioUrl = this.data.vedioUrl 220 | let _this = this 221 | wx.showLoading({ 222 | title: '正在保存...', 223 | mask: true 224 | }) 225 | const downloadTask = wx.downloadFile({ 226 | url: _vedioUrl, 227 | success(res) { 228 | //保存视频到本地 229 | _this.setData({ 230 | 'percent': '100' 231 | }) 232 | wx.saveVideoToPhotosAlbum({ 233 | filePath: res.tempFilePath, 234 | success(res) { 235 | wx.showToast({ 236 | title: '保存成功', 237 | }) 238 | _this.initStat() 239 | }, 240 | fail(err) { 241 | _this.initStat() 242 | if (err.errMsg === "saveVideoToPhotosAlbum:fail auth deny") { 243 | wx.openSetting({ 244 | success(res) { 245 | if (res.authSetting['scope.writePhotosAlbum']) { 246 | wx.showToast({ 247 | title: '请再次保存视频', 248 | icon: 'none' 249 | }) 250 | } else { 251 | wx.showToast({ 252 | title: '请先允许授权', 253 | icon: 'none' 254 | }) 255 | } 256 | } 257 | }) 258 | } 259 | } 260 | }) 261 | }, 262 | fail(res) { 263 | wx.showToast({ 264 | title: '请复制视频链接去外部浏览器下载', 265 | icon: 'none' 266 | }) 267 | } 268 | }) 269 | 270 | downloadTask.onProgressUpdate((res) => { 271 | _this.setData({ 272 | 'percent': '95', 273 | downStart: true, 274 | showProgress: true 275 | }) 276 | }) 277 | }, 278 | 279 | /** 280 | * 复制前判断剪切板有没有内容 281 | */ 282 | confirmClip: function () { 283 | let _this = this 284 | wx.getClipboardData({ 285 | success(res) { 286 | let _clipData = res.data 287 | if (_clipData.indexOf('http') >= 0) { 288 | wx.showModal({ 289 | title: '提示', 290 | content: '检测到您的剪贴板有链接是否需要粘贴?', 291 | success(res) { 292 | if (res.confirm) { 293 | _clipData = _this.formatUrl(_clipData) 294 | _this.setData({ 295 | 'removeUrl': _clipData, 296 | 'showCancel': true 297 | }) 298 | } 299 | } 300 | }) 301 | } 302 | } 303 | }) 304 | }, 305 | 306 | /** 307 | * 复制 308 | */ 309 | copyUrl: function () { 310 | let _type = this.data.type 311 | let _vedioUrl = this.data.vedioUrl 312 | wx.setClipboardData({ 313 | data: _vedioUrl, 314 | success(res) { 315 | wx.showToast({ 316 | title: '复制成功', 317 | }) 318 | }, 319 | fail(res) { 320 | wx.showToast({ 321 | title: '复制失败', 322 | icon: 'none' 323 | }) 324 | } 325 | }) 326 | }, 327 | 328 | /** 329 | * 清除视频连接 330 | */ 331 | clearUrl: function () { 332 | this.setData({ 333 | 'removeUrl': '', 334 | 'showCancel': false 335 | }) 336 | }, 337 | 338 | /** 339 | * 获取文案中的链接 340 | */ 341 | formatUrl: function (url) { 342 | if(url.indexOf('http') >= 0) { 343 | let reg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g 344 | let _data = reg.exec(url) 345 | if(_data) { 346 | url = encodeURI(_data[0]) 347 | } 348 | } 349 | return url 350 | }, 351 | 352 | /** 353 | * 保存完成状态复原 354 | */ 355 | initStat: function () { 356 | wx.hideLoading() 357 | this.setData({ 358 | showProgress: false 359 | }) 360 | } 361 | }) -------------------------------------------------------------------------------- /utils/md5.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 3 | * Digest Algorithm, as defined in RFC 1321. 4 | * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 6 | * Distributed under the BSD License 7 | * See http://pajhome.org.uk/crypt/md5 for more info. 8 | */ 9 | 10 | /* 11 | * Configurable variables. You may need to tweak these to be compatible with 12 | * the server-side, but the defaults work in most cases. 13 | */ 14 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ 15 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ 16 | 17 | /* 18 | * These are the functions you'll usually want to call 19 | * They take string arguments and return either hex or base-64 encoded strings 20 | */ 21 | function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); } 22 | function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); } 23 | function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); } 24 | function hex_hmac_md5(k, d) 25 | { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } 26 | function b64_hmac_md5(k, d) 27 | { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } 28 | function any_hmac_md5(k, d, e) 29 | { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } 30 | 31 | /* 32 | * Perform a simple self-test to see if the VM is working 33 | */ 34 | function md5_vm_test() 35 | { 36 | return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72"; 37 | } 38 | 39 | /* 40 | * Calculate the MD5 of a raw string 41 | */ 42 | function rstr_md5(s) 43 | { 44 | return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); 45 | } 46 | 47 | /* 48 | * Calculate the HMAC-MD5, of a key and some data (raw strings) 49 | */ 50 | function rstr_hmac_md5(key, data) 51 | { 52 | var bkey = rstr2binl(key); 53 | if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); 54 | 55 | var ipad = Array(16), opad = Array(16); 56 | for(var i = 0; i < 16; i++) 57 | { 58 | ipad[i] = bkey[i] ^ 0x36363636; 59 | opad[i] = bkey[i] ^ 0x5C5C5C5C; 60 | } 61 | 62 | var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); 63 | return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); 64 | } 65 | 66 | /* 67 | * Convert a raw string to a hex string 68 | */ 69 | function rstr2hex(input) 70 | { 71 | try { hexcase } catch(e) { hexcase=0; } 72 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 73 | var output = ""; 74 | var x; 75 | for(var i = 0; i < input.length; i++) 76 | { 77 | x = input.charCodeAt(i); 78 | output += hex_tab.charAt((x >>> 4) & 0x0F) 79 | + hex_tab.charAt( x & 0x0F); 80 | } 81 | return output; 82 | } 83 | 84 | /* 85 | * Convert a raw string to a base-64 string 86 | */ 87 | function rstr2b64(input) 88 | { 89 | try { b64pad } catch(e) { b64pad=''; } 90 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 91 | var output = ""; 92 | var len = input.length; 93 | for(var i = 0; i < len; i += 3) 94 | { 95 | var triplet = (input.charCodeAt(i) << 16) 96 | | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) 97 | | (i + 2 < len ? input.charCodeAt(i+2) : 0); 98 | for(var j = 0; j < 4; j++) 99 | { 100 | if(i * 8 + j * 6 > input.length * 8) output += b64pad; 101 | else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); 102 | } 103 | } 104 | return output; 105 | } 106 | 107 | /* 108 | * Convert a raw string to an arbitrary string encoding 109 | */ 110 | function rstr2any(input, encoding) 111 | { 112 | var divisor = encoding.length; 113 | var i, j, q, x, quotient; 114 | 115 | /* Convert to an array of 16-bit big-endian values, forming the dividend */ 116 | var dividend = Array(Math.ceil(input.length / 2)); 117 | for(i = 0; i < dividend.length; i++) 118 | { 119 | dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); 120 | } 121 | 122 | /* 123 | * Repeatedly perform a long division. The binary array forms the dividend, 124 | * the length of the encoding is the divisor. Once computed, the quotient 125 | * forms the dividend for the next step. All remainders are stored for later 126 | * use. 127 | */ 128 | var full_length = Math.ceil(input.length * 8 / 129 | (Math.log(encoding.length) / Math.log(2))); 130 | var remainders = Array(full_length); 131 | for(j = 0; j < full_length; j++) 132 | { 133 | quotient = Array(); 134 | x = 0; 135 | for(i = 0; i < dividend.length; i++) 136 | { 137 | x = (x << 16) + dividend[i]; 138 | q = Math.floor(x / divisor); 139 | x -= q * divisor; 140 | if(quotient.length > 0 || q > 0) 141 | quotient[quotient.length] = q; 142 | } 143 | remainders[j] = x; 144 | dividend = quotient; 145 | } 146 | 147 | /* Convert the remainders to the output string */ 148 | var output = ""; 149 | for(i = remainders.length - 1; i >= 0; i--) 150 | output += encoding.charAt(remainders[i]); 151 | 152 | return output; 153 | } 154 | 155 | /* 156 | * Encode a string as utf-8. 157 | * For efficiency, this assumes the input is valid utf-16. 158 | */ 159 | function str2rstr_utf8(input) 160 | { 161 | var output = ""; 162 | var i = -1; 163 | var x, y; 164 | 165 | while(++i < input.length) 166 | { 167 | /* Decode utf-16 surrogate pairs */ 168 | x = input.charCodeAt(i); 169 | y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; 170 | if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) 171 | { 172 | x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); 173 | i++; 174 | } 175 | 176 | /* Encode output as utf-8 */ 177 | if(x <= 0x7F) 178 | output += String.fromCharCode(x); 179 | else if(x <= 0x7FF) 180 | output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 181 | 0x80 | ( x & 0x3F)); 182 | else if(x <= 0xFFFF) 183 | output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 184 | 0x80 | ((x >>> 6 ) & 0x3F), 185 | 0x80 | ( x & 0x3F)); 186 | else if(x <= 0x1FFFFF) 187 | output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 188 | 0x80 | ((x >>> 12) & 0x3F), 189 | 0x80 | ((x >>> 6 ) & 0x3F), 190 | 0x80 | ( x & 0x3F)); 191 | } 192 | return output; 193 | } 194 | 195 | /* 196 | * Encode a string as utf-16 197 | */ 198 | function str2rstr_utf16le(input) 199 | { 200 | var output = ""; 201 | for(var i = 0; i < input.length; i++) 202 | output += String.fromCharCode( input.charCodeAt(i) & 0xFF, 203 | (input.charCodeAt(i) >>> 8) & 0xFF); 204 | return output; 205 | } 206 | 207 | function str2rstr_utf16be(input) 208 | { 209 | var output = ""; 210 | for(var i = 0; i < input.length; i++) 211 | output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, 212 | input.charCodeAt(i) & 0xFF); 213 | return output; 214 | } 215 | 216 | /* 217 | * Convert a raw string to an array of little-endian words 218 | * Characters >255 have their high-byte silently ignored. 219 | */ 220 | function rstr2binl(input) 221 | { 222 | var output = Array(input.length >> 2); 223 | for(var i = 0; i < output.length; i++) 224 | output[i] = 0; 225 | for(var i = 0; i < input.length * 8; i += 8) 226 | output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); 227 | return output; 228 | } 229 | 230 | /* 231 | * Convert an array of little-endian words to a string 232 | */ 233 | function binl2rstr(input) 234 | { 235 | var output = ""; 236 | for(var i = 0; i < input.length * 32; i += 8) 237 | output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); 238 | return output; 239 | } 240 | 241 | /* 242 | * Calculate the MD5 of an array of little-endian words, and a bit length. 243 | */ 244 | function binl_md5(x, len) 245 | { 246 | /* append padding */ 247 | x[len >> 5] |= 0x80 << ((len) % 32); 248 | x[(((len + 64) >>> 9) << 4) + 14] = len; 249 | 250 | var a = 1732584193; 251 | var b = -271733879; 252 | var c = -1732584194; 253 | var d = 271733878; 254 | 255 | for(var i = 0; i < x.length; i += 16) 256 | { 257 | var olda = a; 258 | var oldb = b; 259 | var oldc = c; 260 | var oldd = d; 261 | 262 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); 263 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); 264 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); 265 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); 266 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); 267 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); 268 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); 269 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); 270 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); 271 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); 272 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063); 273 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); 274 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); 275 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); 276 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); 277 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); 278 | 279 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); 280 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); 281 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); 282 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); 283 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); 284 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); 285 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); 286 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); 287 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); 288 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); 289 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); 290 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); 291 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); 292 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); 293 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); 294 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); 295 | 296 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); 297 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); 298 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); 299 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); 300 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); 301 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); 302 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); 303 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); 304 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); 305 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); 306 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); 307 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); 308 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); 309 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); 310 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); 311 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); 312 | 313 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); 314 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); 315 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); 316 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); 317 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); 318 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); 319 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); 320 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); 321 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); 322 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); 323 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); 324 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); 325 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); 326 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); 327 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); 328 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); 329 | 330 | a = safe_add(a, olda); 331 | b = safe_add(b, oldb); 332 | c = safe_add(c, oldc); 333 | d = safe_add(d, oldd); 334 | } 335 | return Array(a, b, c, d); 336 | } 337 | 338 | /* 339 | * These functions implement the four basic operations the algorithm uses. 340 | */ 341 | function md5_cmn(q, a, b, x, s, t) 342 | { 343 | return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); 344 | } 345 | function md5_ff(a, b, c, d, x, s, t) 346 | { 347 | return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); 348 | } 349 | function md5_gg(a, b, c, d, x, s, t) 350 | { 351 | return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); 352 | } 353 | function md5_hh(a, b, c, d, x, s, t) 354 | { 355 | return md5_cmn(b ^ c ^ d, a, b, x, s, t); 356 | } 357 | function md5_ii(a, b, c, d, x, s, t) 358 | { 359 | return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); 360 | } 361 | 362 | /* 363 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally 364 | * to work around bugs in some JS interpreters. 365 | */ 366 | function safe_add(x, y) 367 | { 368 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); 369 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); 370 | return (msw << 16) | (lsw & 0xFFFF); 371 | } 372 | 373 | /* 374 | * Bitwise rotate a 32-bit number to the left. 375 | */ 376 | function bit_rol(num, cnt) 377 | { 378 | return (num << cnt) | (num >>> (32 - cnt)); 379 | } 380 | 381 | module.exports = { 382 | hex_md5: hex_md5 383 | } --------------------------------------------------------------------------------