Greasy Fork 还支持 简体中文。

DDNSTO自动续期

路由器插件ddnsto免费套餐续期。

目前為 2021-08-30 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         DDNSTO自动续期
// @icon         https://www.ddnsto.com/app/favicon.ico
// @namespace    http://www.ddnsto.com/
// @version      0.1.0
// @description  路由器插件ddnsto免费套餐续期。
// @author       ddnsto
// @match        *www.ddnsto.com/*
// @require      https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.5.1/jquery.min.js
// @grant        none
// @license      MIT
// @run-at       document-end
// ==/UserScript==

(function () {
        'use strict';
        $('head').append('<script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/layer/3.1.1/layer.min.js"></script>');

        setTimeout(function () {
            let myHref = window.location.href;
            let product, userprd, requestUrl, requestData, is_async, method;
            let nowTime = Date.now();
            let daySeconds = 24 * 60 * 60 * 1000;//每天有多少毫秒
            let feeDiff = 4;
            let tipsLable = '.user';

            if (myHref.indexOf('app/#/devices') !== -1) {
                //获取用户产品列表
                requestUrl = 'https://www.ddnsto.com/api/user/routers/?limit=50&offset=0';
                is_async = false;
                doRequest(function (res) {
                    if (res.hasOwnProperty('results')) {
                        let tempUserprd = res.results;
                        let i = 0;
                        userprd = {};
                        $.each(tempUserprd, (k, v) => {
                            if (v.hasOwnProperty('has_active_non_free_plan') && v.has_active_non_free_plan === false) {
                                userprd[i] = v;
                                i++;
                            }
                        });
                    }
                });

                let is_return = false;
                if (empty(userprd)) {
                    layerTips('用户免费套餐为空,不执行续期操作。');
                    is_return = true;
                } else if (userprd.length > 1) {
                    layerTips('用户有两个免费套餐,不执行续期操作。');
                    is_return = true;
                }

                let userPrdinfo = userprd[0];
                if (empty(userPrdinfo)) {
                    layerTips('用户免费套餐为空,不执行续期操作。');
                    is_return = true;
                }

                let exprieTime = Date.parse(userPrdinfo.active_plan.product_expired_at);
                let diffTime = exprieTime - nowTime;
                if (diffTime > feeDiff * daySeconds) {
                    let diffDays = (diffTime / daySeconds).toFixed(1);
                    layerTips('当前免费套餐有效期:' + diffDays + '天。<br>套餐有效期大于' + feeDiff + '天,停止自动续期。');
                    is_return = true;
                }

                if (is_return) {
                    return;
                }

                //获取可用免费套餐
                requestUrl = 'https://www.ddnsto.com/api/user/product/products/';
                is_async = false;
                doRequest(function (res) {
                    $.each(res, (k, v) => {
                        if (v.hasOwnProperty('price') && parseInt(v.price) === 0) {
                            product = v;
                        }
                    });
                });

                //执行下单操作。
                requestUrl = 'https://www.ddnsto.com/api/user/product/orders/';
                requestData = {product_id: product.id, uuid_from_client: generateUUID()};
                method = 'post';
                doRequest(function (res) {
                    let order_id = res.id;
                    //查询订单,并不知道有什么用。
                    requestUrl = 'https://www.ddnsto.com/api/user/product/orders/' + order_id + '/';
                    doRequest(function (res) {
                        requestUrl = userprd[0].url;
                        requestData = {plan_ids_to_add: [order_id], server: userprd[0].server};
                        method = 'patch';
                        doRequest(function (res) {
                            let expireDate = res.longest_plan_due_date;
                            let routerName = res.name;
                            layerTips('续期成功,路由器 ' + routerName + '<br>当前到期时间:' + utc2beijing(expireDate));
                        });
                    });
                });
            }

            function doRequest(callback) {
                if (is_async === undefined) {
                    is_async = true;
                } else {
                    is_async = is_async === true;
                }
                if (!method) {
                    method = 'get';
                }
                if (!requestUrl) {
                    alert('未设置url,请检查代码');
                    return;
                }
                let opt = {
                    type: method.toUpperCase(),
                    async: is_async,
                    url: requestUrl,
                    contentType: "application/json;charset=UTF-8", //必须这样写
                    dataType: "json",
                    beforeSend: function (request) {
                        request.setRequestHeader("x-csrftoken", getCsrfToken());
                    },
                    success: function (res) {
                        callback(res);
                    },
                };

                if (requestData !== undefined && requestData) {

                    opt.data = JSON.stringify(requestData);
                }

                method = requestUrl = is_async = requestData = undefined;

                $.ajax(opt);
            }

            function generateUUID() {
                let d = new Date().getTime();
                if (window.performance && typeof window.performance.now === "function") {
                    d += performance.now(); //use high-precision timer if available
                }
                let uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                    let r = (d + Math.random() * 16) % 16 | 0;
                    d = Math.floor(d / 16);
                    return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
                });
                return uuid;
            }

            function getCsrfToken() {
                return getCookie('csrftoken');
            }

            function getCookie(name) {
                let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
                if (arr = document.cookie.match(reg))
                    return unescape(arr[2]);
                else
                    return null;
            }

            function getStorge(name, type) {
                if (type === 'session') {
                    return sessionStorage.getItem(name);
                }
                return localStorage.getItem(name);
            }

            function setStorge(name, data, type) {
                if (type === 'session') {
                    return sessionStorage.setItem(name, data);
                }
                return localStorage.setItem(name, data);
            }

            function removeStorge(name, type) {
                if (type === 'session') {
                    return sessionStorage.removeItem(name);
                }
                return localStorage.removeItem(name)
            }

            function empty(value) {
                let ret = false;
                if (!value) {
                    ret = true;
                }

                return ret;
            }

            function utc2beijing(utc_datetime) {
                // 转为正常的时间格式 年-月-日 时:分:秒
                var T_pos = utc_datetime.indexOf('T');
                var Z_pos = utc_datetime.indexOf('Z');
                var year_month_day = utc_datetime.substr(0, T_pos);
                var hour_minute_second = utc_datetime.substr(T_pos + 1, Z_pos - T_pos - 1);
                var new_datetime = year_month_day + " " + hour_minute_second; // 2017-03-31 08:02:06

                // 处理成为时间戳
                var timestamp = new Date(Date.parse(new_datetime));
                timestamp = timestamp.getTime();
                timestamp = timestamp / 1000;

                // 增加8个小时,北京时间比utc时间多八个时区
                timestamp = timestamp + 8 * 60 * 60;

                var date = new Date(parseInt(timestamp) * 1000);
                var year = date.getFullYear();
                var mon = date.getMonth() + 1;
                var day = date.getDate();
                var hour = date.getHours();
                var min = date.getMinutes();

                // 时间戳转为时间
                return year + '年' + mon + '月' + day + '日 ' + hour + ':' + min;
            }

            /**
             * 弹出layer tips
             * @param msg
             */
            function layerTips(msg) {
                layer.tips(msg, tipsLable, {tips: 1});
            }
        }, 1000);
    }
)();