banner
MACSITE

@MACSITE

兴趣是学习的动力,学习也能成为消遣!--你愁啥-ncs.fun

Qexo Friend Link Hexo-Next Theme Adaptation

I’m really confused#

The CDN's JS library is invalid, the file is gone, and it's all third-party adaptations. The official link application adaptation provided is no longer usable.

Although it's ugly, it works 😬

I originally wanted to take a screenshot for comparison, but it's gone

There are really too many pitfalls. I suggest friends download the JS and CSS locally; if it fails, you won't be able to use it.#

<div id="friends-api"></div>
<script src="https://cdn.jsdelivr.net/gh/Fgaoxing/blog-cdn@main/source/js/friends-api.js"></script>
<script>qexo_friend_api("friends-api","Qexo domain");</script>

https://cdn.jsdelivr.net/gh/Fgaoxing/blog-cdn@main/source/js/friends-api.js

JS is invalid#

This is the friend link application API adapted by @Fgaoxing provided by the official website.

Just a few days ago, it was still working when I tested it 😵

What I modified#

Using the next theme adapted for the Icarus friend link application page.

Let’s get straight to the code, if there’s an error.

First, generate the links page, everyone knows how to do that, right? Just like generating the about page.

Then edit the index.md inside links.

---
title: Friend Links
date: 2023-03-29 13:53:04
type: "links"
# Comment function is turned off by default
comments: false
---
<div id="qexo-friends"></div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/qexo-static@1.1.3/hexo/friends/friends.css"/>
<script src="https://cdn.jsdelivr.net/npm/qexo-static@1.1.3/hexo/friends/friends.js"></script>
<script>loadQexoFriends("qexo-friends", "https://your interface")</script>

<script src=https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js></script>
<link rel=stylesheet href=https://cdn.staticfile.org/font-awesome/5.15.4/css/all.min.css>
<link rel=stylesheet href=https://your css url/css-js/friends-api.css>
<article class="message is-info">
    <div class="message-header">
        Apply for Friend Links
    </div>
    <div class="message-body">
        <div class="form-ask-friend">
            <div class="field">
                <label class="label">Name</label>
                <div class="control has-icons-left">
                    <input class="input" type="text" placeholder="Your site name" id="friend-name" required>
                    <span class="icon is-small is-left">
                        <i class="fas fa-signature"></i>
                    </span>
                </div>
            </div>
            <div class="field">
                <label class="label">Link</label>
            <div class="control has-icons-left">
                <input class="input" type="url" placeholder="Link to your website's homepage" id="friend-link" required>
                <span class="icon is-small is-left">
                    <i class="fas fa-link"></i>
                </span>
            </div>
            <p class="help ">Please ensure the site is accessible!</p>
            </div>
            <div class="field">
                <label class="label">Icon</label>
                <div class="control has-icons-left">
                    <input class="input" type="url" placeholder="Your website icon (preferably round)" id="friend-icon" required>
                    <span class="icon is-small is-left">
                        <i class="fas fa-image"></i>
                    </span>
                </div>
            </div>
            <div class="field">
                <label class="label">Description</label>
                <div class="control has-icons-left">
                    <input class="input" type="text" placeholder="Please introduce your site in one sentence" id="friend-des" required>
                    <span class="icon is-small is-left">
                        <i class="fas fa-info"></i>
                    </span>
                </div>
            </div>
            <div class="field">
                <div class="control">
                    <label class="checkbox">
                        <input type="checkbox" id="friend-check"/> The information I submitted is not meaningless
                    </label>
                </div>
            </div>
            <div class="field is-grouped">
                <div class="control">
                    <button class="button is-info" type="submit" onclick="askFriend(event)" id="commitbtn">Apply for Friend Links</button>
                </div>
            </div>
        </div>
    </div>
</article>
<script src="https://recaptcha.net/recaptcha/api.js?render=your reCaptcha key"></script>
<script>
function TestUrl(url) {
    var Expression=/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
    var objExp=new RegExp(Expression);
    if(objExp.test(url) != true){
        return false;
    }
    return true;
}
function askFriend (event) {
    let check = $("#friend-check").is(":checked");
    let name = $("#friend-name").val();
    let url = $("#friend-link").val();
    let image = $("#friend-icon").val();
    let des = $("#friend-des").val();
    if(!check){
        alert("Please check \"The information I submitted is not meaningless\"");
        return;
    }
    if(!(name&&url&&image&&des)){
        alert("Information is incomplete! ");
        return;
    }
    if (!(TestUrl(url))){
        alert("URL format error! It needs to include HTTP protocol header! ");
        return;
    }
    if (!(TestUrl(image))){
        alert("Image URL format error! It needs to include HTTP protocol header! ");
        return;
    }
    event.target.classList.add('is-loading');
    grecaptcha.ready(function() {
          grecaptcha.execute('your reCaptcha key', {action: 'submit'}).then(function(token) {
              $.ajax({
                type: 'get',
                cache: false,
                url: url,
                dataType: "jsonp",
                async: false,
                processData: false,
                //timeout:10000, 
                complete: function (data) {
                    if(data.status==200){
                    $.ajax({
                        type: 'POST',
                        dataType: "json",
                        data: {
                            "name": name,
                            "url": url,
                            "image": image,
                            "description": des,
                            "verify": token,
                        },
                        url: 'https://qexo.ncs.fun/pub/ask_friend/',
                        success: function (data) {
                            alert(data.msg);
                        }
                    });}
                    else{
                        alert("URL cannot be connected! Please refresh and change the link content and try again");
                    }
                    event.target.classList.remove('is-loading');
                }
          });
        });
    });
document.getElementById("commitbtn").setAttribute("disabled", true);
document.getElementById("commitbtn").innerHTML = 'Button is invalid😁, please wait for the success prompt, it may be a bit slow😒';
}
</script>

Note#

<link rel=stylesheet href=https://your css url/css-js/friends-api.css>

Below is the CSS code

@-moz-keyframes spinAround {
	from {
	transform:rotate(0)
}
to {
	transform:rotate(359deg)
}
}@-webkit-keyframes spinAround {
	from {
	transform:rotate(0)
}
to {
	transform:rotate(359deg)
}
}@-o-keyframes spinAround {
	from {
	transform:rotate(0)
}
to {
	transform:rotate(359deg)
}
}@keyframes spinAround {
	from {
	transform:rotate(0)
}
to {
	transform:rotate(359deg)
}
}.breadcrumb,.button,.delete,.file,.is-unselectable,.modal-close,.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous,.tabs {
	-webkit-touch-callout:none;
	-webkit-user-select:none;
	-moz-user-select:none;
	-ms-user-select:none;
	user-select:none
}
.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after {
	border:3px solid transparent;
	border-radius:2px;
	border-right:0;
	border-top:0;
	content:" ";
	display:block;
	height:.625em;
	margin-top:-.4375em;
	pointer-events:none;
	position:absolute;
	top:50%;
	transform:rotate(-45deg);
	transform-origin:center;
	width:.625em
}
.button.is-loading::after,.control.is-loading::after,.loader,.select.is-loading::after {
	animation:spinAround .5s infinite linear;
	border:2px solid #dbdbdb;
	border-radius:290486px;
	border-right-color:transparent;
	border-top-color:transparent;
	content:"";
	display:block;
	height:1em;
	position:relative;
	width:1em
}

html {
    height: 100%;
    -webkit-text-size-adjust: 100%;
    -moz-text-size-adjust: 100%;
    -ms-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

html {
	background-color:#f7f7f7;
	font-size:14px;
	-moz-osx-font-smoothing:grayscale;
	-webkit-font-smoothing:antialiased;
	min-width:300px;
	overflow-x:hidden;
	overflow-y:scroll;
	text-rendering:optimizeLegibility;
	text-size-adjust:100%
}

.button {
    /* background-color: #fff; */
    /* border-color: #dbdbdb; */
    /* border-width: 1px; */
    /* color: #363636; */
    cursor: pointer;
    justify-content: center;
    padding-bottom: calc(0.375em - 1px);
    padding-left: 1em;
    padding-right: 1em;
    padding-top: calc(0.375em - 1px);
    text-align: center;
    white-space: nowrap;
}

.button,.file-cta,.file-name,.input,.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous,.select select,.textarea {
	-moz-appearance:none;
	-webkit-appearance:none;
	align-items:center;
	border:1px solid transparent;
	border-radius:4px;
	box-shadow:none;
	display:inline-flex;
	font-size:1rem;
	height:2.25em;
	justify-content:flex-start;
	line-height:1.5;
	padding-bottom:calc(.5em - 1px);
	padding-left:calc(.75em - 1px);
	padding-right:calc(.75em - 1px);
	padding-top:calc(.5em - 1px);
	position:relative;
	vertical-align:top
}

.button.is-info {
    background-color: #222;
    border-color: transparent;
    color: #fff;
}
.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after {
	border:3px solid transparent;
	border-radius:2px;
	border-right:0;
	border-top:0;
	content:" ";
	display:block;
	height:.625em;
	margin-top:-.4375em;
	pointer-events:none;
	position:absolute;
	top:50%;
	transform:rotate(-45deg);
	transform-origin:center;
	width:.625em
}

.message-header {
	align-items:center;
	background-color:#4a4a4a;
	border-radius:4px 4px 0 0;
	color:#fff;
	display:flex;
	font-weight:700;
	justify-content:space-between;
	line-height:1.25;
	padding:.75em 1em;
	position:relative
}

.message-header+.message-body {
	border-width:0;
	border-top-left-radius:0;
	border-top-right-radius:0
}
.message-body {
	border-color:#dbdbdb;
	border-radius:4px;
	border-style:solid;
	border-width:0 0 0 4px;
	color:#4a4a4a;
	padding:1.25em 1.5em
}

.button.is-info {
	font-weight: 900;
}

.icon {
	align-items:center;
	display:inline-flex;
	justify-content:center;
	height:1.5rem;
	width:1.5rem
}

.input,.select select,.textarea {
	background-color:#fff;
	border-color:#dbdbdb;
	border-radius:4px;
	color:#363636
}

.input::-webkit-input-placeholder,.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder {
	color:rgba(54,54,54,.3)
}

.input[disabled]::-webkit-input-placeholder,.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder {
	color:rgba(122,122,122,.3)
}

.input,.textarea {
	box-shadow:inset 0 .0625em .125em rgba(10,10,10,.05);
	max-width:100%;
	width:100%
}

.input.is-dark,.textarea.is-dark {
	border-color:#363636
}

.label {
	color:#363636;
	display:block;
	font-size:1rem;
	font-weight:700
}

.help {
	display:block;
	font-size:.75rem;
	margin-top:.25rem
}

@media screen and (max-width:768px) {
	.field-label {
	margin-bottom:.5rem
}
}@media screen and (min-width:769px),print {
	.field-label {
	flex-basis:0;
	flex-grow:1;
	flex-shrink:0;
	margin-right:1.5rem;
	text-align:right
}

.field-label.is-large {
	font-size:1.5rem;
	padding-top:.375em
}

@media screen and (min-width:769px),print {
	.field-body {
	display:flex;
	flex-basis:0;
	flex-grow:5;
	flex-shrink:1
}
{
	margin-right:.75rem
}

}.control {
	box-sizing:border-box;
	clear:both;
	font-size:1rem;
	position:relative;
	text-align:left
}

.control.has-icons-left .input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right .select:focus~.icon {
	color:#4a4a4a
}

.control.has-icons-left .icon,.control.has-icons-right .icon {
	color:#dbdbdb;
	height:2.25em;
	pointer-events:none;
	position:absolute;
	top:0;
	width:2.25em;
	z-index:4
}
.control.has-icons-left .input,.control.has-icons-left .select select {
	padding-left:2.25em
}
.control.has-icons-left .icon.is-left {
	left:0
}

*, ::after, ::before {
    box-sizing: inherit;
}

.message.is-info {
    background-color: #f5f5f5;
}

.article .content {
	overflow:auto
}

@media screen and (min-width:768px) {
	.navbar-logo img {
	padding-left:inherit
}
}.grecaptcha-badge {
	display:none
}

.checkbox, .radio {
    cursor: pointer;
    display: inline-block;
    line-height: 1.25;
    position: relative;
}
button, input, select, textarea {
    margin: 0;
}
.control.has-icons-left .icon,.control.has-icons-right .icon {
	color:#dbdbdb;
	height:2.25em;
	pointer-events:none;
	position:absolute;
	top:0;
	width:2.25em;
	z-index:4
}
.control.has-icons-left .input,.control.has-icons-left .select select {
	padding-left:2.25em
}
.control.has-icons-left .icon.is-left {
	left:0
}
.control {
    box-sizing: border-box;
    clear: both;
    font-size: 1rem;
    position: relative;
    text-align: left;
}
*, ::after, ::before {
    box-sizing: inherit;
}

Create a new css-js folder in the source directory and then create a friends-api.css file to write the code into.

This is all over#

Summary#

The blogger adapted the next style and set up a prevention against duplicate submissions. Just look at the code, and if there are any questions, ask in the comments, and I will respond as soon as possible.#

In conclusion#

I found my backup of friends-api.js, hee hee#

function qexo_friend_api(id, url, reCaptcha) {
    qexo_url = url;
    Qexo_reCaptcha_Key = reCaptcha
    var loadStyle = '<div class="qexo_loading"><div class="qexo_part"><div style="display: flex; justify-content: center"><div class="qexo_loader"><div class="qexo_inner one"></div><div class="qexo_inner two"></div><div class="qexo_inner three"></div></div></div></div><p style="text-align: center; display: block">Loading friend link application...</p></div>';
    document.getElementById(id).className = "friend-api";
    document.getElementById(id).innerHTML = loadStyle;
    document.getElementById(id).innerHTML = '<center><p>To apply for a friend link, please first add a friend link to this site</p><div class="friend-api"><style>input.qexo-friend-input {flex: 1 1 0%;display: block;width: 80%;height: calc(1.5em + 1.25rem + 2px);padding: 0.625rem 0.75rem;font-weight: 400;color: #8898aa;box-shadow: 0 3px 2px rgb(233 236 239 / 5%);transition: all 0.15s cubic-bezier(0.68, -0.55, 0.265, 1.55);overflow: visible;margin: 0;font-family: inherit;font-size: inherit;line-height: inherit;position: relative;display: flex;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.05);border-radius: 0.375rem;black;}button.qexo-friend-button {cursor: pointer;position: relative;text-transform: none;transition: all 0.15s ease;letter-spacing: 0.025em;font-size: 0.875rem;will-change: transform;color: #fff;background-color: #5e72e4;border-color: #5e72e4;box-shadow: 0 4px 6px rgb(50 50 93 / 11%), 0 1px 3px rgb(0 0 0 / 8%);vertical-align: middle;cursor: pointer;user-select: none;border: 1px solid transparent;padding: 0.625rem 1.25rem;font-size: 0.875rem;line-height: 1.5;border-radius: 0.25rem;transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;}</style><input type="text" id="qexo_friend_name" class="qexo-friend-input" placeholder="Your site name"><br><input type="text" id="qexo_friend_brief introduction" class="qexo-friend-input" placeholder="Please introduce your site in one sentence"><br><input type="text" id="qexo_friend_website" class="qexo-friend-input"  placeholder="Link to your website's homepage"><br><input type="text" id="qexo_friend_logo" class="qexo-friend-input" placeholder="Your website icon address"><br><button type="button" class="qexo-friend-button" id="qexo-friend-btn" onclick="friend_api()">Apply for Friend Links</button></div></center><br>';
}

function friend_api() {

    document.getElementById('qexo-friend-btn').style.color = '#000';
    document.getElementById('qexo-friend-btn').style.backgroundColor = '#fff';
    document.getElementById('qexo-friend-btn').innerHTML = 'Submitting, please wait...';

    let ask = function (token = '') {
        var name = document.getElementById('qexo_friend_name').value;
        var introduction = document.getElementById('qexo_friend_brief introduction').value;
        var website = document.getElementById('qexo_friend_website').value;
        var logo = document.getElementById('qexo_friend_logo').value;
        var uri = qexo_url + '/pub/ask_friend/';
        if (!name || !website || !logo) {
            document.getElementById('qexo-friend-btn').style.backgroundColor = '#f5365c';
            document.getElementById('qexo-friend-btn').innerHTML = "Please fill in the content first";
            return 0;
        }
        if (!/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/.test(website) || !/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/.test(logo)) {
            document.getElementById('qexo-friend-btn').style.backgroundColor = '#f5365c';
            document.getElementById('qexo-friend-btn').innerHTML = "Please fill in the correct URL with the http header";
            return 0;
        }
        let body = {
            name: name, url: website, image: logo, description: introduction
        }
        if (token) {
            body["verify"] = token;
        }
        data = ''
        for (i in body) {
            data += `&${i}=${encodeURIComponent(body[i])}`
        }
        data = data.slice(1)
        fetch(uri, {
            method: 'post', body: data, headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        }).then(function (data) {
            if (data.ok) {
                data.json().then(function (res) {
                    document.getElementById('qexo-friend-btn').style.color = '#fff';
                    if (res["status"]) {
                        document.getElementById("qexo-friend-btn").setAttribute("disabled", true)
						document.getElementById('qexo-friend-btn').style.backgroundColor = '#2dce89';
                        document.getElementById('qexo-friend-btn').innerHTML = 'Submission successful, please wait for the blogger to confirm! We will no longer remind you of the result, thank you!';
                    } else {
                        document.getElementById('qexo-friend-btn').style.backgroundColor = '#f5365c';
                        document.getElementById('qexo-friend-btn').innerHTML = "Friend link application failed. Prompt: " + res["msg"];
                    }
                });
            } else {
                document.getElementById('qexo-friend-btn').style.color = '#fff';
                document.getElementById('qexo-friend-btn').style.backgroundColor = '#f5365c';
                document.getElementById('qexo-friend-btn').innerHTML = "Network exception!";
            }
        });
    }
    if (Qexo_reCaptcha_Key) {
        grecaptcha.ready(function () {
            grecaptcha.execute(reCaptcha, {action: 'submit'}).then(function (token) {
                ask(token)
            });
        });
    } else {
        ask()
    }
}

If you want to use the original application, feel free to take it 🙄

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.