Github项目
status
Published
date
Feb 18, 2022
slug
github
summary
一些有意思的GitHub库
category
技术分享
tags
记录
Article Details
常用代码
status
Published
date
Feb 18, 2022
slug
code
summary
一些有用的代码
category
技术分享
tags
记录
Flask or FastAPI 系统服务启动
[Unit]
Description=Fastapi
After=network.target

[Service]
User=root
WorkingDirectory=/var/www/html/fast
ExecStart=pipenv run uvicorn main:app --host=:: --port=54321 --reload
Restart=always

[Install]
WantedBy=multi-user.target
CF 绑定域名
const MY_DOMAIN = "n.zdl.im"
const START_PAGE = "3f7143371a2149258e90723a2523bed2"

addEventListener('fetch', event => {
  event.respondWith(fetchAndApply(event.request))
})

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET, HEAD, POST,PUT, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type",
}

function handleOptions(request) {
  if (request.headers.get("Origin") !== null &&
    request.headers.get("Access-Control-Request-Method") !== null &&
    request.headers.get("Access-Control-Request-Headers") !== null) {
    // Handle CORS pre-flight request.
    return new Response(null, {
      headers: corsHeaders
    })
  } else {
    // Handle standard OPTIONS request.
    return new Response(null, {
      headers: {
        "Allow": "GET, HEAD, POST, PUT, OPTIONS",
      }
    })
  }
}

async function fetchAndApply(request) {
  if (request.method === "OPTIONS") {
    return handleOptions(request)
  }
  let url = new URL(request.url)
  let response
  if (url.pathname.startsWith("/app") && url.pathname.endsWith("js")) {
    response = await fetch(`https://www.notion.so${url.pathname}`)
    let body = await response.text()
    try {
      response = new Response(body.replace(/www.notion.so/g, MY_DOMAIN).replace(/notion.so/g, MY_DOMAIN), response)
      // response = new Response(response.body, response)
      response.headers.set('Content-Type', "application/x-javascript")
      console.log("get rewrite app.js")
    } catch (err) {
      console.log(err)
    }

  } else if ((url.pathname.startsWith("/api"))) {
    response = await fetch(`https://www.notion.so${url.pathname}`, {
      body: request.body, // must match 'Content-Type' header
      headers: {
        'content-type': 'application/json;charset=UTF-8',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
      },
      method: "POST", // *GET, POST, PUT, DELETE, etc.
    })
    response = new Response(response.body, response)
    response.headers.set('Access-Control-Allow-Origin', "*")
  } else if (url.pathname === `/`) {
		let pageUrlList = START_PAGE.split("/")
    let redrictUrl = `https://${MY_DOMAIN}/${pageUrlList[pageUrlList.length-1]}`
    return Response.redirect(redrictUrl, 301)
  } else {
    response = await fetch(`https://www.notion.so${url.pathname}`, {
      body: request.body, // must match 'Content-Type' header
      headers: request.headers,
      method: request.method, // *GET, POST, PUT, DELETE, etc.
    })
  }

  return response
}
/* CONFIGURATION STARTS HERE */

  /* Step 1: enter your domain name like notion.afuture.me */
  const MY_DOMAIN = 'n.zdl.im';
  
  /*
   * Step 2: enter your URL slug to page ID mapping
   * The key on the left is the slug (without the slash)
   * The value on the right is the Notion page ID
   */
  const SLUG_TO_PAGE = {
    '': '3f7143371a2149258e90723a2523bed2',
  };
  
  /* Step 3: enter your page title and description for SEO purposes */
  const PAGE_TITLE = '';
  const PAGE_DESCRIPTION = '';
  
  /* Step 4: enter a Google Font name, you can choose from https://fonts.font.im */
  const GOOGLE_FONT = '';
  
  /* Step 5: enter any custom scripts you'd like */
  const CUSTOM_SCRIPT = ``;
  
  /* CONFIGURATION ENDS HERE */
  
  const PAGE_TO_SLUG = {};
  const slugs = [];
  const pages = [];
  Object.keys(SLUG_TO_PAGE).forEach(slug => {
    const page = SLUG_TO_PAGE[slug];
    slugs.push(slug);
    pages.push(page);
    PAGE_TO_SLUG[page] = slug;
  });
  
  addEventListener('fetch', event => {
    event.respondWith(fetchAndApply(event.request));
  });

  function generateSitemap() {
    let sitemap = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
    slugs.forEach(
      (slug) =>
        (sitemap +=
          '<url><loc>https://' + MY_DOMAIN + '/' + slug + '</loc></url>')
    );
    sitemap += '</urlset>';
    return sitemap;
  }
  
  const corsHeaders = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
  };
  
  function handleOptions(request) {
    if (request.headers.get('Origin') !== null &&
      request.headers.get('Access-Control-Request-Method') !== null &&
      request.headers.get('Access-Control-Request-Headers') !== null) {
      // Handle CORS pre-flight request.
      return new Response(null, {
        headers: corsHeaders
      });
    } else {
      // Handle standard OPTIONS request.
      return new Response(null, {
        headers: {
          'Allow': 'GET, HEAD, POST, PUT, OPTIONS',
        }
      });
    }
  }
  
  async function fetchAndApply(request) {
    if (request.method === 'OPTIONS') {
      return handleOptions(request);
    }
    let url = new URL(request.url);
    if (url.pathname === '/robots.txt') {
      return new Response('Sitemap: https://' + MY_DOMAIN + '/sitemap.xml');
    }
    if (url.pathname === '/sitemap.xml') {
      let response = new Response(generateSitemap());
      response.headers.set('content-type', 'application/xml');
      return response;
    }
    const notionUrl = 'https://www.notion.so' + url.pathname;
    let response;
    if (url.pathname.startsWith('/app') && url.pathname.endsWith('js')) {
      response = await fetch(notionUrl);
      let body = await response.text();
      response = new Response(body.replace(/www.notion.so/g, MY_DOMAIN).replace(/notion.so/g, MY_DOMAIN), response);
      response.headers.set('Content-Type', 'application/x-javascript');
    } else if ((url.pathname.startsWith('/api'))) {
      // Forward API
      response = await fetch(notionUrl, {
        body: request.body,
        headers: {
          'content-type': 'application/json;charset=UTF-8',
          'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
        },
        method: 'POST',
      });
      response = new Response(response.body, response);
      response.headers.set('Access-Control-Allow-Origin', '*');
    } else if (slugs.indexOf(url.pathname.slice(1)) > -1) {
      const pageId = SLUG_TO_PAGE[url.pathname.slice(1)];
      return Response.redirect('https://' + MY_DOMAIN + '/' + pageId, 301);
    } else {
      response = await fetch(notionUrl, {
        body: request.body,
        headers: request.headers,
        method: request.method,
      });
      response = new Response(response.body, response);
      response.headers.delete('Content-Security-Policy');
      response.headers.delete('X-Content-Security-Policy');
    }
  
    return appendJavascript(response, SLUG_TO_PAGE);
  }
  
  class MetaRewriter {
    element(element) {
      if (PAGE_TITLE !== '') {
        if (element.getAttribute('property') === 'og:title'
          || element.getAttribute('name') === 'twitter:title') {
          element.setAttribute('content', PAGE_TITLE);
        }
        if (element.tagName === 'title') {
          element.setInnerContent(PAGE_TITLE);
        }
      }
      if (PAGE_DESCRIPTION !== '') {
        if (element.getAttribute('name') === 'description'
          || element.getAttribute('property') === 'og:description'
          || element.getAttribute('name') === 'twitter:description') {
          element.setAttribute('content', PAGE_DESCRIPTION);
        }
      }
      if (element.getAttribute('property') === 'og:url'
        || element.getAttribute('name') === 'twitter:url') {
        element.setAttribute('content', MY_DOMAIN);
      }
      if (element.getAttribute('name') === 'apple-itunes-app') {
        element.remove();
      }
    }
  }
  
  class HeadRewriter {
    element(element) {
      if (GOOGLE_FONT !== '') {
        element.append(`<link href="https://fonts.font.im/css?family=${GOOGLE_FONT.replace(' ', '+')}:Regular,Bold,Italic&display=swap" rel="stylesheet">
        <style>* { font-family: "${GOOGLE_FONT}" !important; }</style>`, {
         html: true
        });
      }
      element.append(`<style>
      div.notion-topbar > div > div:nth-child(3) { display: none !important; }
      div.notion-topbar > div > div:nth-child(4) { display: none !important; }
      div.notion-topbar > div > div:nth-child(5) { display: none !important; }
      div.notion-topbar > div > div:nth-child(6) { display: none !important; }
      div.notion-topbar-mobile > div:nth-child(3) { display: none !important; }
      div.notion-topbar-mobile > div:nth-child(4) { display: none !important; }
      </style>`, {
        html: true
      })
    }
  }
  
  class BodyRewriter {
    constructor(SLUG_TO_PAGE) {
      this.SLUG_TO_PAGE = SLUG_TO_PAGE;
    }
    element(element) {
      element.append(`<div style="display:none">Powered by <a href="http://notion.afuture.me">afuture</a></div>
      <script>
      window.CONFIG.domainBaseUrl = "https://n.zdl.im";
      const SLUG_TO_PAGE = ${JSON.stringify(this.SLUG_TO_PAGE)};
      const PAGE_TO_SLUG = {};
      const slugs = [];
      const pages = [];
      let redirected = false;
      Object.keys(SLUG_TO_PAGE).forEach(slug => {
        const page = SLUG_TO_PAGE[slug];
        slugs.push(slug);
        pages.push(page);
        PAGE_TO_SLUG[page] = slug;
      });
      function getPage() {
        return location.pathname.slice(-32);
      }
      function getSlug() {
        return location.pathname.slice(1);
      }
      function updateSlug() {
        const slug = PAGE_TO_SLUG[getPage()];
        if (slug != null) {
          history.replaceState(history.state, '', '/' + slug);
        }
      }
      const observer = new MutationObserver(function() {
        if (redirected) return;
        const nav = document.querySelector('.notion-topbar');
        const mobileNav = document.querySelector('.notion-topbar-mobile');
        if (nav && nav.firstChild && nav.firstChild.firstChild
          || mobileNav && mobileNav.firstChild) {
          redirected = true;
          updateSlug();
          const onpopstate = window.onpopstate;
          window.onpopstate = function() {
            if (slugs.includes(getSlug())) {
              const page = SLUG_TO_PAGE[getSlug()];
              if (page) {
                history.replaceState(history.state, 'bypass', '/' + page);
              }
            }
            onpopstate.apply(this, [].slice.call(arguments));
            updateSlug();
          };
        }
      });
      observer.observe(document.querySelector('#notion-app'), {
        childList: true,
        subtree: true,
      });
      const replaceState = window.history.replaceState;
      window.history.replaceState = function(state) {
        if (arguments[1] !== 'bypass' && slugs.includes(getSlug())) return;
        return replaceState.apply(window.history, arguments);
      };
      const pushState = window.history.pushState;
      window.history.pushState = function(state) {
        const dest = new URL(location.protocol + location.host + arguments[2]);
        const id = dest.pathname.slice(-32);
        if (pages.includes(id)) {
          arguments[2] = '/' + PAGE_TO_SLUG[id];
        }
        return pushState.apply(window.history, arguments);
      };
      const open = window.XMLHttpRequest.prototype.open;
      window.XMLHttpRequest.prototype.open = function() {
        arguments[1] = arguments[1].replace('${MY_DOMAIN}', 'www.notion.so');
        return open.apply(this, [].slice.call(arguments));
      };
    </script>${CUSTOM_SCRIPT}`, {
        html: true
      });
    }
  }
  
  async function appendJavascript(res, SLUG_TO_PAGE) {
    return new HTMLRewriter()
      .on('title', new MetaRewriter())
      .on('meta', new MetaRewriter())
      .on('head', new HeadRewriter())
      .on('body', new BodyRewriter(SLUG_TO_PAGE))
      .transform(res);
  }
typecho开启https无法登录后台
debian安装redis
vi方向键乱码
安装redis
服务器本地文件互相Copy
 
Article Details
示例文章
status
Published
date
Nov 5, 2021
slug
example
summary
一篇示例的文章
category
学习思考
tags
思考
建站

一、模板使用说明

在模板中,每一篇文章顶部都有以下属性🤔,对应说明如下:
status: 状态,仅Published状态文章会被展示 date: 发布日期 type:类型 分博文(post)单页(page)。单页不会被展示在博文列表。 slug: 文章简短路径 (每篇文章唯一,请勿重复) summary: 内容摘要 category: 分类 tags:标签,支持多个

二、示例段落

1.将进酒

君不见黄河之水天上来,奔流到海不复回。 君不见高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,莫使金樽空对月。 天生我材必有用,千金散尽还复来。 烹羊宰牛且为乐,会须一饮三百杯。 岑夫子,丹丘生,将进酒,杯莫停。 与君歌一曲,请君为我倾耳听。 钟鼓馔玉不足贵,但愿长醉不愿醒。 古来圣贤皆寂寞,惟有饮者留其名。 陈王昔时宴平乐,斗酒十千恣欢谑。 主人何为言少钱,径须沽取对君酌。 五花马、千金裘,呼儿将出换美酒,与尔同销万古愁。

2.代码

@Test
public void test11() {

  long start = System.currentTimeMillis();
  int a = 0;
  for(int i=0;i<1000000000;i++){
      try {
          a++;
      }catch (Exception e){
          e.printStackTrace();
      }
  }
  long useTime = System.currentTimeMillis()-start;
  System.out.println("useTime:"+useTime);
}

3.公式

Article Details
python三要素实名认证接口
status
Published
date
Jun 19, 2021
slug
python01
summary
Python实名认证
category
技术分享
tags
Python
实名认证

说明

利用flask搭建了一个会员中心,需要添加一个实名认证的模块,现在的实名认证一般是银行卡+身份证+姓名或电话号码+身份证+姓名或者支付宝扫脸认证。
选用相对不那么要求隐私的,手机号+身份证+姓名三要素认证。

使用

在阿里云API市场选了一个三要素认证的服务,购买了试用套餐,10条请求的进行测试。
python的给了一个接口的代码,如下:
import urllib, urllib2, sys


host = 'http://sjsys.market.alicloudapi.com'
path = '/communication/personal/1979'
method = 'POST'
appcode = '你自己的AppCode'
querys = ''
bodys = {}
url = host + path

bodys['idcard'] = '''320623198810077180'''
bodys['mobile'] = '''13636643333'''
bodys['name'] = '''张三'''
post_data = urllib.urlencode(bodys)
request = urllib2.Request(url, post_data)
request.add_header('Authorization', 'APPCODE ' + appcode)
//根据API的要求,定义相对应的Content-Type
request.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
response = urllib2.urlopen(request)
content = response.read()
if (content):
    print(content)
然而,这代码太古旧基本用不了了,还好有requests这个神器。
简单修改一下代码如下:
import requests
data = {
    'idcard': '身份证号码',
    'mobile': '手机号码',
    'name': '姓名',
}
url = 'http://sjsys.market.alicloudapi.com/communication/personal/1979'
headers = {
    'Authorization': 'APPCODE ' + 你的appcode,
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
r = requests.post(url=url,data=data,headers=headers)
content = r.text
if (content):
    print(content)
正确的话会返回以下信息:
Article Details
手把手教你用Notion搭建博客
status
Published
date
Jun 9, 2021
slug
NotionBlog
summary
notion搭建博客的方法很多,今天介绍一个Notion+Vercel+Next.js搭建博客的方法。
category
技术分享
tags
notion

说明

notion搭建博客的方法很多,今天介绍一个Notion+Vercel+Next.js搭建博客的方法,作者的Github

演示

演示地址: Sky's Blog

搭建方法

  1. 首先注册一个GitHub账号。
  1. 注册一个Notion账号,创建一个页面,选择右上角Share,选择Share to web,选择Copy link,找到此页面的PageID,就是下图中Blog后面的一串字符。
    1. notion image
  1. 打开此仓库 Fork一份,根据自己的情况修改*site.config.js**的相关内容。
    1. module.exports = {
        // 此处填写第二步中获取到的字符串
        rootNotionPageId: '78fc5a4b88d74b0e824e29407e9f1ec1',
      
        // if you want to restrict pages to a single notion workspace (optional)
        // (this should be a Notion ID; see the docs for how to extract this)
        rootNotionSpaceId: null,
      
        // 站点基础设置
        name: '名称',
        domain: '域名',
        author: '作者',
      
        // 一些其他设置 (可选)
        description: 'Example site description',
        socialImageTitle: 'Transitive Bullshit',
        socialImageSubtitle: 'Hello World! 👋',
      
        // SNS设置 (可选)
        twitter: 'transitive_bs',
        github: 'transitive-bullshit',
        linkedin: 'fisch2',
      
        // default notion icon and cover images for site-wide consistency (optional)
        // page-specific values will override these site-wide defaults
        defaultPageIcon: null,
        defaultPageCover: null,
        defaultPageCoverPosition: 0.5,
      
        // image CDN host to proxy all image requests through (optional)
        // NOTE: this requires you to set up an external image proxy
        imageCDNHost: null,
      
        // Utteranc.es comments via GitHub issue comments (optional)
        utterancesGitHubRepo: null,
      
        // whether or not to enable support for LQIP preview images (optional)
        // NOTE: this requires you to set up Google Firebase and add the environment
        // variables specified in .env.example
        isPreviewImageSupportEnabled: false,
      
        // map of notion page IDs to URL paths (optional)
        // any pages defined here will override their default URL paths
        // example:
        //
        // pageUrlOverrides: {
        //   '/foo': '067dd719a912471ea9a3ac10710e7fdf',
        //   '/bar': '0be6efce9daf42688f65c76b89f8eb27'
        // }
        pageUrlOverrides: null
      }
  1. 打开Vercel,使用Github账号登录,选择New Project,找到Frok过来的库,点击Import
    Article Details
    notion API使用
    status
    Published
    date
    May 19, 2021
    slug
    notionapi
    summary
    使用python添加notion记录
    category
    技术分享
    tags
    Python
    1. 创建一个 Notion 机器人,输入名字,即可快速创建。
    1. 获取Token,点击 show,然后复制备用。
      1. notion image
    1. 在需要使用API的页面中,点击 Share 并选择 Invite ,将机器人邀请进去,让其用于编辑的权限。
      1. notion image
        notion image
    1. 获取数据表的 database_id,点击数据表右上方的 ... 选择 Copylink ,连接如下方:https://www.notion.so/xinhuoip/9bcf00dce55c42799f3b177dc325aa18?v=217bbe82893e4e4aa228a19f3f2dc888 9bcf00dc-e55c-4279-9f3b-177dc325aa18 即为database_id
    1. 使用python的requests库get方法来读取notion页面数据,示例代码如下:
      Article Details