1 Commits

Author SHA1 Message Date
greenkeeper[bot] 904998eca9 docs(readme): add Greenkeeper badge 2018-01-04 16:43:31 +00:00
10 changed files with 20 additions and 605 deletions
-6
View File
@@ -1,6 +0,0 @@
{
"extends": "think",
"rules": {
"camelcase": "off"
}
}
-8
View File
@@ -1,8 +0,0 @@
language: node_js
node_js:
- '8'
sudo: false
script:
- "npm test"
after_success:
- 'npm install coveralls && ./node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls'
-162
View File
@@ -1,162 +0,0 @@
---
date: 2018-01-07T00:00:00+00:00
title: Wechat
author: lizheming
tags: [ notifications, chat ]
repo: lizheming/drone-wechat
logo: wechat.svg
image: lizheming/drone-wechat
---
The Wechat plugin posts build status messages to your account. The below pipeline configuration demonstrates simple usage:
```diff
pipline:
wechat:
image: lizheming/drone-wechat
+ sckey: xxxxxx
title: ${DRONE_REPO_NAME}
message: >
{%if success %}
build {{build.number}} succeeded. Good job.
{% else %}
build {{build.number}} failed. Fix me please.
{% endif %}
```
If you want push notification with your own wechat corp id, you can config like this:
```diff
pipeline:
wechat:
image: lizheming/drone-wechat
+ corpid: corpid
+ corp_secret: secret
+ agent_id: 1234567
+ to_user: 111
+ to_party: 112
+ to_tag: ${DRONE_REPO_NAME}
+ msg_url: ${DRONE_BUILD_LINK}
+ safe: 1
+ btn_txt: more
title: ${DRONE_REPO_NAME}
message: >
{%if success %}
build {{build.number}} succeeded. Good job.
{% else %}
build {{build.number}} failed. Fix me please.
{% endif %}
```
# Parameter Reference
corpid
: The corpid for authorization
corp_secret
: The corp secret for authorization
agent_id:
: The agent id to send the message
to_party
: The party ids to send message
to_user
: The user ids to send the message to
to_tag
: The tag ids to send the message to
safe
: encrypt message, default is false
msg_url
: The link for the text card click
btn_text
: The text for the button on the card
sckey
: SCKEY get from [ServerChan](http://sc.ftqq.com)
title
: Notification title
message
: Notification body message, support markdown
# Secret Reference
wechat\_corpid
: The corpid for authorization
wechat\_corp_secret
: The corp secret for authorization
wechat\_agent\_id
: The agent id to send the message
wechat\_to\_party
: The party ids to send message
wechat\_to\_user
: The user ids to send the message to
wechat\_to\_tag
: The tag ids to send the message to
wechat\_sckey
: SCKEY get from [ServerChan](http://sc.ftqq.com)
# Template Reference
repo.owner
: repository owner
repo.name
: repository name
build.status
: build status type enumeration, either success or failure
build.event
: build event type enumeration, one of push, pull_request, tag, deployment
build.number
: build number
build.commit
: git sha for current commit
build.branch
: git branch for current commit
build.tag
: git tag for current commit
build.ref
: git ref for current commit
build.author
: git author for current commit
build.link
: link the the build results in drone
build.started
: unix timestamp for build started
build.finished
: unix timestamp for build finished
# Template Filter
uppercasefirst
: converts the first letter of a string to uppercase
datetime
: converts a unix timestamp to a date time string. Example {{build.started | datetime}}, you can see more info in [nunjucks-date-filter](https://www.npmjs.com/package/nunjucks-date-filter)
More filter can see [builtin-filters](https://mozilla.github.io/nunjucks/templating.html#builtin-filters)
+2 -2
View File
@@ -1,13 +1,13 @@
FROM mhart/alpine-node:8.9.3
LABEL maintainer="lizheming <i@imnerd.org>" \
org.label-schema.name="Drone Wechat Notification" \
org.label-schema.name="Drone Telegram Node" \
org.label-schema.vendor="lizheming" \
org.label-schema.schema-version="1.0"
WORKDIR /wechat
COPY package.json /wechat/package.json
RUN npm install --production --registry=https://registry.npm.taobao.org
RUN npm install --registry=https://registry.npm.taobao.org
COPY index.js /wechat/index.js
ENTRYPOINT [ "node", "/wechat/index.js" ]
+6 -81
View File
@@ -1,94 +1,19 @@
<img src="wechat.svg" />
## drone-wechat
[![Travis](https://img.shields.io/travis/lizheming/drone-wechat.svg)]()
[![Coverage Status](https://coveralls.io/repos/github/lizheming/drone-wechat/badge.svg?branch=master)](https://coveralls.io/github/lizheming/drone-wechat?branch=master)
[![Docker Pulls](https://img.shields.io/docker/pulls/lizheming/drone-wechat.svg)]()
[![](https://images.microbadger.com/badges/image/lizheming/drone-wechat.svg)](https://microbadger.com/images/lizheming/drone-wechat)
[![GitHub release](https://img.shields.io/github/release/lizheming/drone-wechat.svg)]()
Drone plugin for sending telegram notifications.
[![Greenkeeper badge](https://badges.greenkeeper.io/lizheming/drone-wechat.svg)](https://greenkeeper.io/)
## Description
drone 微信消息通知插件
This drone wechat notification plugin builds base on Wechat for Work. You can config your own wechat corp id, or you can get wechat notification quickly with key from [ServerChan](http://sc.ftqq.com). If you use [ServerChan](http://sc.ftqq.com) you need get `SCKEY` before using. After login with Github account you can get `SCKEY` at http://sc.ftqq.com/?c=code.
## 简介
Read this in other languages: [English](README.md), [简体中文](README.zh-cn.md).
基于 http://sc.ftqq.com/ 封装的 drone 微信消息通知插件。使用前需要去 [Server酱]( http://sc.ftqq.com/) 获取密钥。Github 登录后即可在 [发送消息](http://sc.ftqq.com/?c=code) 页面查看。
## Environment
- `PLUGIN_CORPID`: The corpid for authorization
- `WECHAT_CORPID`: alias for `PLUGIN_CORPID`
- `PLUGIN_CORP_SECRET`: The corp secret for authorization
- `WECHAT_CORP_SECRET`: alias for `PLUGIN_CORP_SECRET`
- `PLUGIN_AGENT_ID`: The agent id to send the message
- `WECHAT_AGENT_ID`: alias for `PLUGIN_AGENT_ID`
- `PLUGIN_TO_PARTY`: The party ids to send the message
- `WECHAT_TO_PARTY`: alias for `PLUGIN_TO_PARTY`
- `PLUGIN_TO_USER`: The user ids to send the message to
- `WECHAT_TO_USER`: alias for `PLUGIN_TO_USER`
- `PLUGIN_TO_TAG`: The tag ids to send the message to
- `WECHAT_TO_TAG`: alias for `PLUGIN_TO_TAG`
- `PLUGIN_SAFE`: encrypt message, default is false
- `PLUGIN_MSG_URL`: The link for the text card click
- `PLUGIN_BTN_TEXT`: The text for the button on the card
- `PLUGIN_SCKEY`: SCKEY get from [ServerChan](http://sc.ftqq.com)
- `WECHAT_SCKEY`: alias for `PLUGIN_SCKEY`
- `PLUGIN_TITLE`: Notification title
- `PLUGIN_MESSAGE`: Notification body message, support markdown.
## Usage
### With wechat corp id
```
docker run --rm \
-e PLUGIN_CORPID=corpid \
-e PLUGIN_CORP_SECRET=corpsecret \
-e PLUGIN_AGENT_ID=agentid \
-e PLUGIN_TO_USER=userId \
-e PLUGIN_TO_TAG=tagId \
-e PLUGIN_TO_PARTY=toParty \
-e PLUGIN_SAFE=1 \
-e PLUGIN_MSG_URL=url \
-e PLUGIN_BTN_TXT=true \
-e PLUGIN_TITLE=title \
-e PLUGIN_MESSAGE=description \
-e DRONE_REPO_OWNER=lizheming \
-e DRONE_REPO_NAME=drone-wechat \
-e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \
-e DRONE_COMMIT_BRANCH=master \
-e DRONE_COMMIT_LINK=https://github.com/lizheming/drone-wechat/compare/master... \
-e DRONE_COMMIT_AUTHOR=lizheming \
-e DRONE_COMMIT_AUTHOR_EMAIL=secretlzm007@gmail.com \
-e DRONE_BUILD_NUMBER=1 \
-e DRONE_BUILD_STATUS=success \
-e DRONE_BUILD_LINK=http://github.com/lizheming/drone-wechat \
-e DRONE_TAG=1.0.0 \
-e DRONE_JOB_STARTED=1477550550 \
-e DRONE_JOB_FINISHED=1477550750 \
lizheming/drone-wechat
```
### With server chan key
## 使用
```
docker run --rm \
-e PLUGIN_SCKEY=xxxx \
-e PLUGIN_TITLE=xxxx \
-e PLUGIN_MESSAGE=xxx \
-e DRONE_REPO_OWNER=lizheming \
-e DRONE_REPO_NAME=drone-wechat \
-e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \
-e DRONE_COMMIT_BRANCH=master \
-e DRONE_COMMIT_LINK=https://github.com/lizheming/drone-wechat/compare/master... \
-e DRONE_COMMIT_AUTHOR=lizheming \
-e DRONE_COMMIT_AUTHOR_EMAIL=secretlzm007@gmail.com \
-e DRONE_BUILD_NUMBER=1 \
-e DRONE_BUILD_STATUS=success \
-e DRONE_BUILD_LINK=http://github.com/lizheming/drone-wechat \
-e DRONE_TAG=1.0.0 \
-e DRONE_JOB_STARTED=1477550550 \
-e DRONE_JOB_FINISHED=1477550750 \
-e PLUGIN_MESSAGE=xxx
lizheming/drone-wechat
```
-94
View File
@@ -1,94 +0,0 @@
<img src="wechat.svg" />
## drone-wechat
[![Travis](https://img.shields.io/travis/lizheming/drone-wechat.svg)]()
[![Coverage Status](https://coveralls.io/repos/github/lizheming/drone-wechat/badge.svg?branch=master)](https://coveralls.io/github/lizheming/drone-wechat?branch=master)
[![Docker Pulls](https://img.shields.io/docker/pulls/lizheming/drone-wechat.svg)]()
[![](https://images.microbadger.com/badges/image/lizheming/drone-wechat.svg)](https://microbadger.com/images/lizheming/drone-wechat)
[![GitHub release](https://img.shields.io/github/release/lizheming/drone-wechat.svg)]()
drone 微信消息通知插件。
其它语言版本:[English](README.md)[简体中文](README.zh-cn.md)。
## 简介
基于微信企业号封装的 drone 微信消息通知插件。你可以设置自己的企业号,也可以使用 [Server酱]( http://sc.ftqq.com/) 来快速配置微信消息通知功能。如果使用 [Server酱]( http://sc.ftqq.com/) 需要在使用前获取密钥。Github 登录后即可在 [发送消息](http://sc.ftqq.com/?c=code) 页面查看。
## 配置说明
- `PLUGIN_CORPID`: 企业Id
- `WECHAT_CORPID`: `PLUGIN_CORPID` 别名
- `PLUGIN_CORP_SECRET`: 管理组的凭证密钥
- `WECHAT_CORP_SECRET`: `PLUGIN_CORP_SECRET` 别名
- `PLUGIN_AGENT_ID`: 企业应用的id,整型。可在应用的设置页面查看
- `WECHAT_AGENT_ID`: `PLUGIN_AGENT_ID` 别名
- `PLUGIN_TO_PARTY`: 部门ID列表,多个接收者用‘|’分隔,最多支持100个。
- `WECHAT_TO_PARTY`: `PLUGIN_TO_PARTY` 别名
- `PLUGIN_TO_USER`: 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向该企业应用的全部成员发送
- `WECHAT_TO_USER`: `PLUGIN_TO_USER` 别名
- `PLUGIN_TO_TAG`: 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
- `WECHAT_TO_TAG`: `PLUGIN_TO_TAG` 别名
- `PLUGIN_SAFE`: 表示是否是保密消息,0表示否,1表示是,默认0
- `PLUGIN_MSG_URL`: 点击后跳转的链接。
- `PLUGIN_BTN_TEXT`: 按钮文字。 默认为“详情”, 不超过4个文字,超过自动截断。
- `PLUGIN_SCKEY`: [Server酱](http://sc.ftqq.com) 申请的密钥
- `WECHAT_SCKEY`: `PLUGIN_SCKEY` 别名
- `PLUGIN_TITLE`: 消息卡片标题
- `PLUGIN_MESSAGE`: 消息卡片正文,支持 Markdown。
## 如何使用
### 自行配置微信企业号
```
docker run --rm \
-e PLUGIN_CORPID=corpid \
-e PLUGIN_CORP_SECRET=corpsecret \
-e PLUGIN_AGENT_ID=agentid \
-e PLUGIN_TO_USER=userId \
-e PLUGIN_TO_TAG=tagId \
-e PLUGIN_TO_PARTY=toParty \
-e PLUGIN_SAFE=1 \
-e PLUGIN_MSG_URL=url \
-e PLUGIN_BTN_TXT=true \
-e PLUGIN_TITLE=title \
-e PLUGIN_MESSAGE=description \
-e DRONE_REPO_OWNER=lizheming \
-e DRONE_REPO_NAME=drone-wechat \
-e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \
-e DRONE_COMMIT_BRANCH=master \
-e DRONE_COMMIT_LINK=https://github.com/lizheming/drone-wechat/compare/master... \
-e DRONE_COMMIT_AUTHOR=lizheming \
-e DRONE_COMMIT_AUTHOR_EMAIL=secretlzm007@gmail.com \
-e DRONE_BUILD_NUMBER=1 \
-e DRONE_BUILD_STATUS=success \
-e DRONE_BUILD_LINK=http://github.com/lizheming/drone-wechat \
-e DRONE_TAG=1.0.0 \
-e DRONE_JOB_STARTED=1477550550 \
-e DRONE_JOB_FINISHED=1477550750 \
lizheming/drone-wechat
```
### 使用Server酱快速集成
```
docker run --rm \
-e PLUGIN_SCKEY=xxxx \
-e PLUGIN_TITLE=xxxx \
-e PLUGIN_MESSAGE=xxx \
-e DRONE_REPO_OWNER=lizheming \
-e DRONE_REPO_NAME=drone-wechat \
-e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \
-e DRONE_COMMIT_BRANCH=master \
-e DRONE_COMMIT_LINK=https://github.com/lizheming/drone-wechat/compare/master... \
-e DRONE_COMMIT_AUTHOR=lizheming \
-e DRONE_COMMIT_AUTHOR_EMAIL=secretlzm007@gmail.com \
-e DRONE_BUILD_NUMBER=1 \
-e DRONE_BUILD_STATUS=success \
-e DRONE_BUILD_LINK=http://github.com/lizheming/drone-wechat \
-e DRONE_TAG=1.0.0 \
-e DRONE_JOB_STARTED=1477550550 \
-e DRONE_JOB_FINISHED=1477550750 \
lizheming/drone-wechat
```
+10 -109
View File
@@ -1,118 +1,19 @@
const process = require('process');
const render = require('drone-render');
const request = require('request-promise-native');
const {
PLUGIN_CORPID,
WECHAT_CORPID,
PLUGIN_CORP_SECRET,
WECHAT_CORP_SECRET,
PLUGIN_AGENT_ID,
WECHAT_AGENT_ID,
PLUGIN_TO_PARTY,
WECHAT_TO_PARTY,
PLUGIN_TO_USER,
WECHAT_TO_USER,
PLUGIN_TO_TAG,
WECHAT_TO_TAG,
PLUGIN_MSG_TYPE,
PLUGIN_SAFE,
PLUGIN_MSG_URL,
PLUGIN_BTN_TEXT,
PLUGIN_SCKEY,
WECHAT_SERVER_CHAN_KEY,
PLUGIN_TITLE,
PLUGIN_MESSAGE
PLUGIN_MESSAGE,
SERVER_CHAN_KEY
} = process.env;
function sendMsgFromServerChan() {
const SCKEY = PLUGIN_SCKEY || WECHAT_SERVER_CHAN_KEY;
if (!SCKEY) {
return false;
const SCKEY = PLUGIN_SCKEY || SERVER_CHAN_KEY;
request({
url: `https://sc.ftqq.com/${SCKEY}.send`,
qs: {
text: PLUGIN_TITLE,
desp: render(PLUGIN_MESSAGE)
}
request({
url: `https://sc.ftqq.com/${SCKEY}.send`,
qs: {
text: PLUGIN_TITLE,
desp: render(PLUGIN_MESSAGE)
}
});
return true;
}
function getAccessToken() {
const CORPID = PLUGIN_CORPID || WECHAT_CORPID;
const CORP_SECRET = PLUGIN_CORP_SECRET || WECHAT_CORP_SECRET;
return request({
url: 'https://qyapi.weixin.qq.com/cgi-bin/gettoken',
qs: {
corpid: CORPID,
corpsecret: CORP_SECRET
},
json: true
}).then(resp => {
if (!resp.access_token) {
throw new Error(resp);
}
return resp.access_token;
});
}
function sendMsgFromWork(access_token) {
const TO_USER = PLUGIN_TO_USER || WECHAT_TO_USER || '@all';
const TO_PARTY = PLUGIN_TO_PARTY || WECHAT_TO_PARTY;
const TO_TAG = PLUGIN_TO_TAG || WECHAT_TO_TAG;
const AGENT_ID = PLUGIN_AGENT_ID || WECHAT_AGENT_ID;
const MSG_TYPE = PLUGIN_MSG_TYPE || 'textcard';
const SAFE = PLUGIN_SAFE || 0;
const TITLE = PLUGIN_TITLE;
const DESCRIPTION = render(PLUGIN_MESSAGE);
const MSG_URL = PLUGIN_MSG_URL;
const BTN_TEXT = PLUGIN_BTN_TEXT;
return request({
method: 'POST',
url: 'https://qyapi.weixin.qq.com/cgi-bin/message/send',
qs: {
access_token
},
body: {
touser: TO_USER,
toparty: TO_PARTY,
tag: TO_TAG,
msgtype: MSG_TYPE,
agentid: AGENT_ID,
safe: SAFE,
textcard: {
title: TITLE,
description: DESCRIPTION,
url: MSG_URL,
btntext: BTN_TEXT
}
},
json: true
});
}
function sendMsgFromWechat() {
return getAccessToken()
.then(sendMsgFromWork)
.catch(err => {
console.error(err);
});
}
sendMsgFromServerChan() || sendMsgFromWechat();
module.exports = {
sendMsgFromServerChan,
getAccessToken,
sendMsgFromWork,
sendMsgFromWechat
};
});
+2 -11
View File
@@ -1,12 +1,10 @@
{
"name": "drone-wechat",
"version": "1.1.0",
"version": "0.0.1",
"description": "drone wechat notification plugin",
"main": "index.js",
"scripts": {
"test": "npm run eslint && npm run test-cov",
"test-cov": "nyc ava test.js && nyc report --reporter=html",
"eslint": "eslint index.js"
"test": "\"\""
},
"repository": {
"type": "git",
@@ -28,12 +26,5 @@
"drone-render": "^1.0.0",
"request": "^2.83.0",
"request-promise-native": "^1.0.5"
},
"devDependencies": {
"ava": "^0.24.0",
"eslint": "^4.14.0",
"eslint-config-think": "^1.0.2",
"mock-require": "^2.0.2",
"nyc": "^11.4.1"
}
}
-131
View File
@@ -1,131 +0,0 @@
const {test} = require('ava');
const mock = require('mock-require');
const SCKEY = 'testsckey';
const SCKEY2 = 'testsckey2';
const TITLE = 'test for title';
const MESSAGE = 'test for message';
test('send wechat with serverchan', async t => {
t.plan(2);
mock('process', {
env: {
PLUGIN_SCKEY: SCKEY,
PLUGIN_TITLE: TITLE,
PLUGIN_MESSAGE: MESSAGE
}
});
mock('drone-render', text => {
t.is(text, MESSAGE);
return text + '1';
});
mock('request-promise-native', obj => {
t.deepEqual(obj, {
url: `https://sc.ftqq.com/${SCKEY}.send`,
qs: {
text: TITLE,
desp: MESSAGE + '1'
}
});
});
mock.reRequire('./index.js');
mock.stopAll();
});
test('get wechat corp access token', async t => {
t.plan(3);
mock('process', {
env: {
PLUGIN_CORPID: 111,
PLUGIN_CORP_SECRET: 222,
PLUGIN_TITLE: TITLE,
PLUGIN_MESSAGE: MESSAGE
}
});
mock('request-promise-native', obj => {
if (obj.url.includes('gettoken')) {
t.deepEqual(obj, {
url: 'https://qyapi.weixin.qq.com/cgi-bin/gettoken',
qs: {
corpid: 111,
corpsecret: 222
},
json: true
});
}
return Promise.resolve({access_token: 1234});
});
const wechat = mock.reRequire('./index');
t.is(1234, await wechat.getAccessToken());
mock.stopAll();
});
test('send wechat with corp id', async t => {
mock('process', {
env: {
PLUGIN_TITLE: TITLE,
PLUGIN_MESSAGE: MESSAGE,
PLUGIN_TO_PARTY: 'party',
PLUGIN_TO_TAG: 'tag',
PLUGIN_MSG_URL: '',
PLUGIN_BTN_TEXT: 'more',
PLUGIN_AGENT_ID: 1122
}
});
mock('request-promise-native', obj => {
if (obj.url.includes('gettoken')) {
return Promise.resolve({access_token: 1234});
}
if (obj.url.includes('send')) {
t.deepEqual(obj, {
method: 'POST',
url: 'https://qyapi.weixin.qq.com/cgi-bin/message/send',
qs: {
access_token: 1234
},
body: {
touser: '@all',
toparty: 'party',
tag: 'tag',
msgtype: 'textcard',
agentid: 1122,
safe: 0,
textcard: {
title: TITLE,
description: MESSAGE,
url: '',
btntext: 'more'
}
},
json: true
});
}
});
mock.reRequire('./index');
mock.stopAll();
});
test('send wechat', async t => {
mock('process', {
env: {
PLUGIN_TITLE: TITLE,
PLUGIN_MESSAGE: MESSAGE
}
});
mock('request-promise-native', obj => {
if (obj.url.includes('gettoken')) {
return Promise.resolve({errcode: 1, errmsg: 123});
}
if (obj.url.includes('send')) {
t.fail();
}
});
mock.reRequire('./index');
await new Promise(resolve => setTimeout(resolve, 2000)).then(() => t.pass());
mock.stopAll();
});
-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 300 300"><path fill="#2DC100" d="M300 255c0 24.854-20.147 45-45 45H45c-24.854 0-45-20.146-45-45V45C0 20.147 20.147 0 45 0h210c24.853 0 45 20.147 45 45v210z"/><g fill="#FFF"><path d="M200.803 111.88c-24.213 1.265-45.268 8.605-62.362 25.188-17.271 16.754-25.155 37.284-23 62.734-9.464-1.172-18.084-2.462-26.753-3.192-2.994-.252-6.547.106-9.083 1.537-8.418 4.75-16.488 10.113-26.053 16.092 1.755-7.938 2.891-14.889 4.902-21.575 1.479-4.914.794-7.649-3.733-10.849-29.066-20.521-41.318-51.232-32.149-82.85 8.483-29.25 29.315-46.989 57.621-56.236 38.635-12.62 82.054.253 105.547 30.927 8.485 11.08 13.688 23.516 15.063 38.224zm-111.437-9.852c.223-5.783-4.788-10.993-10.74-11.167-6.094-.179-11.106 4.478-11.284 10.483-.18 6.086 4.475 10.963 10.613 11.119 6.085.154 11.186-4.509 11.411-10.435zm58.141-11.171c-5.974.11-11.022 5.198-10.916 11.004.109 6.018 5.061 10.726 11.204 10.652 6.159-.074 10.83-4.832 10.772-10.977-.051-6.032-4.981-10.79-11.06-10.679z"/><path d="M255.201 262.83c-7.667-3.414-14.7-8.536-22.188-9.318-7.459-.779-15.3 3.524-23.104 4.322-23.771 2.432-45.067-4.193-62.627-20.432-33.397-30.89-28.625-78.254 10.014-103.568 34.341-22.498 84.704-14.998 108.916 16.219 21.129 27.24 18.646 63.4-7.148 86.284-7.464 6.623-10.15 12.073-5.361 20.804.884 1.612.985 3.653 1.498 5.689zm-87.274-84.499c4.881.005 8.9-3.815 9.085-8.636.195-5.104-3.91-9.385-9.021-9.406-5.06-.023-9.299 4.318-9.123 9.346.166 4.804 4.213 8.69 9.059 8.696zm56.261-18.022c-4.736-.033-8.76 3.844-8.953 8.629-.205 5.117 3.772 9.319 8.836 9.332 4.898.016 8.768-3.688 8.946-8.562.19-5.129-3.789-9.364-8.829-9.399z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB