├── .gitignore
├── README.md
├── client
├── .DS_Store
├── app.js
├── app.json
├── app.wxss
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ ├── map
│ │ ├── map.js
│ │ ├── map.json
│ │ ├── map.wxml
│ │ └── map.wxss
│ └── result
│ │ ├── result.js
│ │ ├── result.json
│ │ ├── result.wxml
│ │ └── result.wxss
├── source
│ └── icon.png
└── utils
│ └── util.js
├── restart_service.sh
├── server
├── .vscode
│ ├── launch.json
│ └── settings.json
└── server.py
├── uwsgi_config.ini
└── wsgi.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 | .hypothesis/
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 | local_settings.py
55 |
56 | # Flask stuff:
57 | instance/
58 | .webassets-cache
59 |
60 | # Scrapy stuff:
61 | .scrapy
62 |
63 | # Sphinx documentation
64 | docs/_build/
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # IPython Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # dotenv
79 | .env
80 |
81 | # virtualenv
82 | venv/
83 | ENV/
84 |
85 | # Spyder project settings
86 | .spyderproject
87 |
88 | # Rope project settings
89 | .ropeproject
90 |
91 | #macos
92 | .DS_Store
93 | .vscode/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # net_tool_wechat_xiaochengxu
2 |
3 | ### Glance
4 | 
5 | ### Dependency
6 | - CentOS 7.x
7 | - python3.x, flask
8 | - nginx, uwsgi, supervisord
9 |
10 | ### IP API
11 | - ip api : https://freegeoip.net/json/
12 |
13 | ### install & configuration
14 | 1. supervisord file :/etc/supervisord.d/nettool.ini
15 | ```
16 | [supervisord]
17 | [program:nettool]
18 | command=uwsgi uwsgi_config.ini
19 | directory=/home/www/source
20 | user=root
21 |
22 | autostart=true
23 | autorestart=true
24 | ```
25 |
26 | `you may need to comment 'server' block in /etc/nginx/nginx.conf`
27 |
28 | 2. niginx configuration file : /etc/nginx/conf.d/nettool.conf
29 | ```
30 | server {
31 | listen 80;
32 | server_name server_domain_or_IP;
33 | return 301 https://$server_name$request_uri;
34 | }
35 | server {
36 | listen 443 ssl;
37 | server_name server_domain_or_IP;
38 | ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;
39 | ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
40 |
41 | location / {
42 | include uwsgi_params;
43 | uwsgi_pass unix:/home/user/myproject/myproject.sock;
44 | }
45 | }
46 |
47 | ```
48 | 3. run `sh restart_service.sh`
49 |
--------------------------------------------------------------------------------
/client/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/heemoe/net_tool_wechat_xiaochengxu/8538f79a9d13d8654ad02139b5cfeca786ca21f7/client/.DS_Store
--------------------------------------------------------------------------------
/client/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | }
5 | })
--------------------------------------------------------------------------------
/client/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages":[
3 | "pages/index/index",
4 | "pages/result/result"
5 | ],
6 | "window":{
7 | "backgroundTextStyle":"light",
8 | "navigationBarBackgroundColor": "#fff",
9 | "navigationBarTitleText": "NetTool",
10 | "navigationBarTextStyle":"black"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/client/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | .view-center{
3 | text-align: center;
4 | }
--------------------------------------------------------------------------------
/client/pages/index/index.js:
--------------------------------------------------------------------------------
1 | //index.js
2 | //获取应用实例
3 | var app = getApp()
4 | var input_value = ""
5 | const baseIpUrl = "https://freegeoip.net/json/"
6 |
7 | Page({
8 | data: {
9 | focus : true,
10 | input_placeholder : "输入你要查询的URL~"
11 | },
12 | endInputting: function(e){
13 | console.log(e.detail.value)
14 | input_value = e.detail.value;
15 | },
16 | pingBtnClick: function() {
17 | if (!checkInputValue()){
18 | return
19 | }
20 | wx.navigateTo({
21 | url: '../result/result?type=ping' + inputValueParameter()
22 | })
23 | },
24 | digBtnClick: function() {
25 | if (!checkInputValue()){
26 | return
27 | }
28 | wx.navigateTo({
29 | url: '../result/result?type=dig' + inputValueParameter()
30 | })
31 | },
32 | whoisBtnClick: function() {
33 | if (!checkInputValue()){
34 | return
35 | }
36 | wx.navigateTo({
37 | url: '../result/result?type=whois' + inputValueParameter()
38 | })
39 | },
40 | ipBtnClick: function() {
41 | if (!checkInputValue()){
42 | return
43 | }
44 | wx.navigateTo({
45 | url: '../result/result?type=ip' + inputValueParameter()
46 | })
47 | },
48 | ipv6BtnClick: function() {
49 | if (!checkInputValue()){
50 | return
51 | }
52 | wx.request({
53 | url: baseIpUrl + input_value,
54 | success: function(res) {
55 | console.log(res)
56 | if (res.statusCode != 200){
57 | wx.showModal({
58 | title: "请输入正确的URL或者IP地址!",
59 | showCancel: false,
60 | })
61 | }
62 | var obj = res.data
63 | wx.openLocation({
64 | latitude: obj.latitude,
65 | longitude: obj.longitude,
66 | scale: 14
67 | })
68 | },
69 | fail: function() {
70 | wx.showModal({
71 | title: "请求失败!",
72 | showCancel: false
73 | })
74 | }
75 | })
76 | }
77 | })
78 | function checkInputValue() {
79 | if (!input_value.includes(".")){
80 | wx.showModal({
81 | title: "请输入正确的URL或者IP地址!",
82 | showCancel: false
83 | })
84 | return false
85 | }
86 | return true
87 | }
88 |
89 | function inputValueParameter(){
90 | return "&value=" + input_value;
91 | }
--------------------------------------------------------------------------------
/client/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/client/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/client/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | /**index.wxss**/
2 | .head_view{
3 | text-align: center;
4 | }
5 | .head_img {
6 | width:50px;
7 | height:50px;
8 | }
9 | .kwd_view {
10 | margin-top:30px
11 | }
12 | .kwd_view_input {
13 | height:60px;
14 | border-bottom:solid;
15 | border-top:solid;
16 | border-color:#05ce0e;
17 | border-width:1px
18 | }
19 | .buttons {
20 | margin-top: 30px
21 | }
22 | .button {
23 | height: 44px;
24 | width: 70%;
25 | margin-bottom: 10px;
26 | }
--------------------------------------------------------------------------------
/client/pages/map/map.js:
--------------------------------------------------------------------------------
1 | const baseIpUrl = "https://freegeoip.net/json/"
2 | Page({
3 | data: {
4 | lon: "23.099994",
5 | lat: "113.324520"
6 | },
7 | onLoad: function(options){
8 | const that = this
9 | // console.log(options)
10 | wx.setNavigationBarTitle({
11 | title: options.type
12 | })
13 | wx.request({
14 | url: baseIpUrl + options.value,
15 | success: function(res) {
16 | console.log(res)
17 | if (res.statusCode != 200){
18 | wx.showModal({
19 | title: "请输入正确的URL或者IP地址!",
20 | showCancel: false,
21 | success: function(res) {
22 | if (res.confirm){
23 | wx.navigateBack()
24 | }
25 | }
26 | })
27 | }
28 | var obj = res.data
29 | wx.openLocation({
30 | latitude: obj.latitude,
31 | longitude: obj.longitude,
32 | scale: 28
33 | })
34 | return
35 | that.setData({
36 | lon: obj.longitude,
37 | lat: obj.latitude
38 | })
39 | },
40 | fail: function() {
41 | wx.showModal({
42 | title: "请求失败!",
43 | showCancel: false,
44 | success: function(res) {
45 | if (res.confirm){
46 | wx.navigateBack()
47 | }
48 | }
49 | })
50 | }
51 | })
52 | }
53 | })
54 |
55 |
--------------------------------------------------------------------------------
/client/pages/map/map.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/client/pages/map/map.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/client/pages/map/map.wxss:
--------------------------------------------------------------------------------
1 | .map {
2 | width: 100%;
3 | height: 736px;
4 | }
--------------------------------------------------------------------------------
/client/pages/result/result.js:
--------------------------------------------------------------------------------
1 | const baseServerUrl = "https://DOMAIN/api/v1.0/nettool/"
2 | const baseIpUrl = "https://freegeoip.net/json/"
3 | Page({
4 | data: {
5 | result: "..."
6 | },
7 | onLoad: function(options){
8 | const that = this
9 | // console.log(options)
10 | wx.setNavigationBarTitle({
11 | title: options.type
12 | })
13 |
14 | if (options.type == "ip"){
15 | wx.request({
16 | url: baseIpUrl + options.value,
17 | success: function(res) {
18 | console.log(res.data)
19 | if (!isSucucessCode(res.statusCode)){
20 | return;
21 | }
22 | var obj = res.data
23 | that.setData({
24 | result: "ip:" + obj.ip + "\n" +
25 | "country_code: " + obj.country_code + "\n" +
26 | "country_name: " + obj.country_name + "\n" +
27 | "region_code: " + obj.region_code + "\n" +
28 | "region_name: " + obj.region_name + "\n" +
29 | "city: " + obj.city + "\n" +
30 | "zip_code: " + obj.zip_code + "\n" +
31 | "time_zone: " + obj.time_zone + "\n"
32 | })
33 | },
34 | fail: function() {
35 | that.setData({
36 | result: "数据获取失败..."
37 | })
38 | }
39 | })
40 | return
41 | }
42 |
43 | wx.request({
44 | url: baseServerUrl + options.type + "/" + options.value,
45 | success: function(res) {
46 | console.log(res.data)
47 | if (!isSucucessCode(res.statusCode)){
48 | return;
49 | }
50 | that.setData({
51 | result: res.data
52 | })
53 | },
54 | fail: function() {
55 | that.setData({
56 | result: "数据获取失败..."
57 | })
58 | }
59 | })
60 | }
61 | })
62 | function isSucucessCode(code){
63 | if (code != 200){
64 | wx.showModal({
65 | title: "请输入正确的URL或者IP地址!",
66 | showCancel: false,
67 | success: function(res) {
68 | if (res.confirm){
69 | wx.navigateBack()
70 | }
71 | }
72 | })
73 | return false
74 | }
75 | return true
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/client/pages/result/result.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/client/pages/result/result.wxml:
--------------------------------------------------------------------------------
1 |
2 | {{result}}
3 |
--------------------------------------------------------------------------------
/client/pages/result/result.wxss:
--------------------------------------------------------------------------------
1 | .result_view {
2 | margin: 200px,200px,200px,200px
3 | }
4 | .result_content_label {
5 | margin-top: 60px;
6 | font-size: 14px;
7 | }
--------------------------------------------------------------------------------
/client/source/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/heemoe/net_tool_wechat_xiaochengxu/8538f79a9d13d8654ad02139b5cfeca786ca21f7/client/source/icon.png
--------------------------------------------------------------------------------
/client/utils/util.js:
--------------------------------------------------------------------------------
1 | function formatTime(date) {
2 | var year = date.getFullYear()
3 | var month = date.getMonth() + 1
4 | var day = date.getDate()
5 |
6 | var hour = date.getHours()
7 | var minute = date.getMinutes()
8 | var second = date.getSeconds()
9 |
10 |
11 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
12 | }
13 |
14 | function formatNumber(n) {
15 | n = n.toString()
16 | return n[1] ? n : '0' + n
17 | }
18 |
19 | module.exports = {
20 | formatTime: formatTime
21 | }
22 |
--------------------------------------------------------------------------------
/restart_service.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/sh
2 | killall supervisord
3 | supervisord -c /etc/supervisord.d/nettool.ini
4 | service nginx restart
--------------------------------------------------------------------------------
/server/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Flask",
6 | "type": "python",
7 | "request": "launch",
8 | "stopOnEntry": false,
9 | "pythonPath":"${config:python.pythonPath}",
10 | "program": "${workspaceRoot}/wsgi.py",
11 | "cwd": "${workspaceRoot}",
12 | "args": [],
13 | "env": {},
14 | "envFile": "${workspaceRoot}/.env",
15 | "debugOptions": [
16 | "WaitOnAbnormalExit",
17 | "WaitOnNormalExit",
18 | "RedirectOutput"
19 | ]
20 | }
21 | ]
22 | }
--------------------------------------------------------------------------------
/server/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | }
--------------------------------------------------------------------------------
/server/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | from flask import Flask
3 | from flask import jsonify
4 | from flask import request
5 | from flask import abort
6 | import subprocess
7 |
8 | app = Flask(__name__)
9 |
10 |
11 | @app.route('/', methods=['GET'])
12 | def get_home():
13 | return "
Hello World!
"
14 |
15 |
16 | @app.route('/api/v1.0/nettool//', methods=['GET'])
17 | def get_net_tool(type, keyword):
18 | # print(request.args.get('summary'))
19 | # print(request.args.get('charge'))
20 | print(type + keyword)
21 | if type == "dig" or type == "whois" or type == "ping" and keyword and "." in keyword:
22 | value = data_from_type(type, keyword)
23 | return value
24 | else:
25 | abort(400)
26 | return None
27 |
28 |
29 | def data_from_type(cmd, kwd):
30 | cmds = [cmd, kwd]
31 | if cmd == "ping":
32 | cmds = [cmd, "-c", "3", kwd]
33 | # value = subprocess.run(cmds, stdout=subprocess.PIPE).stdout
34 | print(cmds)
35 | proc = subprocess.Popen(cmds, stdout=subprocess.PIPE)
36 | value = ''
37 | for line in proc.stdout:
38 | value += line.decode() + '\n'
39 | print(value)
40 | return value
41 |
--------------------------------------------------------------------------------
/uwsgi_config.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | module = wsgi
3 | callable = app
4 | master = true
5 | processes = 1
6 | chdir = /home/www/source/
7 |
8 | socket = nettool.sock
9 | chmod-socket = 666
10 | vacuum = true
11 |
12 | die-on-term = true
--------------------------------------------------------------------------------
/wsgi.py:
--------------------------------------------------------------------------------
1 | from server.server import app
2 |
3 | if __name__ == "__main__":
4 | app.run()
5 |
--------------------------------------------------------------------------------