├── .dockerignore
├── .gitattributes
├── .github
└── workflows
│ └── dockerimage.yml
├── .gitignore
├── Dockerfile
├── Dockerfile-slim
├── LICENSE
├── README.md
├── apps
├── api
│ ├── __init__.py
│ ├── permissions.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── blog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── context_processors.py
│ ├── feeds.py
│ ├── management
│ │ └── commands
│ │ │ └── clear_cache.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_article_is_publish.py
│ │ ├── 0003_auto_20230702_1043.py
│ │ ├── 0004_auto_20230702_1134.py
│ │ ├── 0005_auto_20230702_1623.py
│ │ ├── 0006_auto_20230708_0641.py
│ │ ├── 0007_auto_20230709_1237.py
│ │ ├── 0008_auto_20230710_1613.py
│ │ ├── 0009_auto_20230713_1223.py
│ │ ├── 0010_auto_20230715_1407.py
│ │ ├── 0011_auto_20230715_1443.py
│ │ ├── 0012_auto_20230727_1929.py
│ │ ├── 0013_articleview.py
│ │ ├── 0014_auto_20231208_1310.py
│ │ ├── 0015_pageview.py
│ │ ├── 0016_pageview_is_compute.py
│ │ ├── 0017_feedhub.py
│ │ ├── 0018_auto_20240101_1903.py
│ │ ├── 0019_menulink.py
│ │ ├── 0020_auto_20240409_1309.py
│ │ └── __init__.py
│ ├── models.py
│ ├── search_indexes.py
│ ├── signals.py
│ ├── sitemaps.py
│ ├── static
│ │ └── blog
│ │ │ ├── bootstrap
│ │ │ ├── 3.0.2
│ │ │ │ └── css
│ │ │ │ │ └── bootstrap.min.css
│ │ │ ├── 3.3.1
│ │ │ │ └── js
│ │ │ │ │ └── bootstrap.min.js
│ │ │ ├── 3.3.7
│ │ │ │ ├── css
│ │ │ │ │ └── bootstrap.min.css
│ │ │ │ ├── fonts
│ │ │ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ │ │ └── glyphicons-halflings-regular.woff2
│ │ │ │ └── js
│ │ │ │ │ └── bootstrap.min.js
│ │ │ └── 4.3.1
│ │ │ │ ├── css
│ │ │ │ └── bootstrap.min.css
│ │ │ │ └── js
│ │ │ │ └── bootstrap.min.js
│ │ │ ├── css
│ │ │ ├── account.css
│ │ │ ├── base.css
│ │ │ ├── detail.css
│ │ │ ├── monokai-2.css
│ │ │ ├── monokai.css
│ │ │ ├── night.css
│ │ │ └── timeline.css
│ │ │ ├── font-awesome
│ │ │ └── 4.7.0
│ │ │ │ ├── css
│ │ │ │ └── font-awesome.min.css
│ │ │ │ └── fonts
│ │ │ │ ├── fontawesome-webfont.eot
│ │ │ │ ├── fontawesome-webfont.svg
│ │ │ │ ├── fontawesome-webfont.ttf
│ │ │ │ ├── fontawesome-webfont.woff
│ │ │ │ └── fontawesome-webfont.woff2
│ │ │ ├── img
│ │ │ ├── 404.png
│ │ │ ├── TOP.png
│ │ │ ├── baidu-2.png
│ │ │ ├── blog.png
│ │ │ ├── chrome.png
│ │ │ ├── docker.png
│ │ │ ├── favicon.ico
│ │ │ ├── friend.png
│ │ │ ├── github.png
│ │ │ ├── html.png
│ │ │ ├── map.png
│ │ │ ├── nav-logo.png
│ │ │ ├── regex.png
│ │ │ ├── reward_wx.png
│ │ │ ├── reward_zfb.png
│ │ │ ├── rss.png
│ │ │ ├── summary.png
│ │ │ ├── toggle-dark.png
│ │ │ ├── toggle-light.png
│ │ │ └── word-cloud.png
│ │ │ ├── js
│ │ │ ├── article.js
│ │ │ ├── base.js
│ │ │ ├── code.js
│ │ │ ├── echarts
│ │ │ │ └── 5.4.3
│ │ │ │ │ └── echarts.min.js
│ │ │ ├── headroom.min.js
│ │ │ ├── html5shiv
│ │ │ │ └── 3.7.2
│ │ │ │ │ └── html5shiv.min.js
│ │ │ ├── jq
│ │ │ │ ├── 1.11.1
│ │ │ │ │ └── jquery.min.js
│ │ │ │ └── 3.3.1
│ │ │ │ │ └── jquery.min.js
│ │ │ ├── js.cookie.min.js
│ │ │ ├── popper.min.js
│ │ │ └── respond
│ │ │ │ └── 1.4.2
│ │ │ │ └── respond.min.js
│ │ │ └── simplemde
│ │ │ └── 1.11.2
│ │ │ ├── simplemde.min.css
│ │ │ └── simplemde.min.js
│ ├── templates
│ │ └── blog
│ │ │ ├── about.html
│ │ │ ├── archive.html
│ │ │ ├── articleEdit.html
│ │ │ ├── base.html
│ │ │ ├── category.html
│ │ │ ├── dashboard.html
│ │ │ ├── detail.html
│ │ │ ├── feedhub.html
│ │ │ ├── friend.html
│ │ │ ├── friendAdd.html
│ │ │ ├── index.html
│ │ │ ├── silian.xml
│ │ │ ├── subject.html
│ │ │ ├── subjectDetail.html
│ │ │ ├── subjectIndex.html
│ │ │ ├── tag.html
│ │ │ ├── tags
│ │ │ ├── article_list.html
│ │ │ ├── base_right.html
│ │ │ ├── carousel.html
│ │ │ ├── menulink.html
│ │ │ ├── navbar.html
│ │ │ ├── pagecut.html
│ │ │ └── reward.html
│ │ │ └── timeline.html
│ ├── templatetags
│ │ ├── __init__.py
│ │ ├── blog_tags.py
│ │ └── dashboard.py
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ ├── views.py
│ └── whoosh_cn_backend.py
├── comment
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_systemnotification.py
│ │ ├── 0003_auto_20230708_0641.py
│ │ └── __init__.py
│ ├── models.py
│ ├── signals.py
│ ├── static
│ │ └── comment
│ │ │ ├── css
│ │ │ ├── base_comment.css
│ │ │ └── notification.css
│ │ │ ├── emoji
│ │ │ ├── +1.png
│ │ │ ├── angry.png
│ │ │ ├── anguished.png
│ │ │ ├── blush.png
│ │ │ ├── broken_heart.png
│ │ │ ├── clap.png
│ │ │ ├── cold_sweat.png
│ │ │ ├── confounded.png
│ │ │ ├── cry.png
│ │ │ ├── disappointed_relieved.png
│ │ │ ├── dizzy_face.png
│ │ │ ├── dog.png
│ │ │ ├── fearful.png
│ │ │ ├── fist.png
│ │ │ ├── flushed.png
│ │ │ ├── frowning.png
│ │ │ ├── grin.png
│ │ │ ├── heart.png
│ │ │ ├── heart_eyes.png
│ │ │ ├── heartbeat.png
│ │ │ ├── hushed.png
│ │ │ ├── innocent.png
│ │ │ ├── joy.png
│ │ │ ├── kissing_closed_eyes.png
│ │ │ ├── kissing_heart.png
│ │ │ ├── mask.png
│ │ │ ├── no_mouth.png
│ │ │ ├── pensive.png
│ │ │ ├── persevere.png
│ │ │ ├── pray.png
│ │ │ ├── relieved.png
│ │ │ ├── scream.png
│ │ │ ├── sleepy.png
│ │ │ ├── smile.png
│ │ │ ├── smiley.png
│ │ │ ├── smirk.png
│ │ │ ├── sob.png
│ │ │ ├── sparkling_heart.png
│ │ │ ├── stuck_out_tongue.png
│ │ │ ├── stuck_out_tongue_closed_eyes.png
│ │ │ ├── stuck_out_tongue_winking_eye.png
│ │ │ ├── sunglasses.png
│ │ │ ├── sweat.png
│ │ │ ├── sweat_smile.png
│ │ │ ├── unamused.png
│ │ │ ├── v.png
│ │ │ ├── worried.png
│ │ │ └── yum.png
│ │ │ ├── js
│ │ │ ├── activate-power.js
│ │ │ ├── editor.js
│ │ │ └── notification.js
│ │ │ └── weibo
│ │ │ ├── aini_org.png
│ │ │ ├── baibai_thumb.png
│ │ │ ├── baobao_thumb.png
│ │ │ ├── beishang_org.png
│ │ │ ├── bingbujiandan_thumb.png
│ │ │ ├── bishi_org.png
│ │ │ ├── bizui_org.png
│ │ │ ├── chanzui_org.png
│ │ │ ├── chigua_thumb.png
│ │ │ ├── chongjing_org.png
│ │ │ ├── dahaqian_org.png
│ │ │ ├── dalian_org.png
│ │ │ ├── ding_org.png
│ │ │ ├── doge02_org.png
│ │ │ ├── erha_org.png
│ │ │ ├── gui_org.png
│ │ │ ├── guzhang_thumb.png
│ │ │ ├── haha_thumb.png
│ │ │ ├── heng_thumb.png
│ │ │ ├── huaixiao_org.png
│ │ │ ├── huaxin_org.png
│ │ │ ├── jiyan_org.png
│ │ │ ├── kelian_org.png
│ │ │ ├── ku_org.png
│ │ │ ├── kuxiao_org.png
│ │ │ ├── leimu_org.png
│ │ │ ├── miaomiao_thumb.png
│ │ │ ├── ningwen_org.png
│ │ │ ├── nu_thumb.png
│ │ │ ├── qian_thumb.png
│ │ │ ├── sikao_org.png
│ │ │ ├── taikaixin_org.png
│ │ │ ├── tanshou_org.png
│ │ │ ├── tianping_thumb.png
│ │ │ ├── touxiao_org.png
│ │ │ ├── tu_org.png
│ │ │ ├── wabi_thumb.png
│ │ │ ├── weiqu_thumb.png
│ │ │ ├── wenhao_thumb.png
│ │ │ ├── wosuanle_thumb.png
│ │ │ ├── wu_thumb.png
│ │ │ ├── xiaoerbuyu_org.png
│ │ │ ├── xiaoku_thumb.png
│ │ │ ├── xixi_thumb.png
│ │ │ ├── yinxian_org.png
│ │ │ ├── yun_thumb.png
│ │ │ ├── zhouma_thumb.png
│ │ │ └── zhuakuang_org.png
│ ├── templates
│ │ └── comment
│ │ │ ├── comment_form.html
│ │ │ ├── comment_list.html
│ │ │ └── notification.html
│ ├── templatetags
│ │ ├── __init__.py
│ │ └── comment_tags.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── easytask
│ ├── __init__.py
│ ├── actions.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tasks.py
│ ├── tests.py
│ ├── utils.py
│ └── views.py
├── monitor
│ ├── __init__.py
│ ├── actions.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_monitorserver_active.py
│ │ ├── 0003_monitorserver_alarm.py
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── monitor
│ │ │ ├── css
│ │ │ └── monitor.css
│ │ │ ├── img
│ │ │ ├── DSM.svg
│ │ │ ├── centos.svg
│ │ │ ├── debian.svg
│ │ │ ├── linux.svg
│ │ │ ├── mac-os.svg
│ │ │ ├── redhat.svg
│ │ │ ├── ubuntu.svg
│ │ │ └── windows.svg
│ │ │ └── js
│ │ │ └── monitor.js
│ ├── templates
│ │ └── monitor
│ │ │ ├── base.html
│ │ │ ├── demo.html
│ │ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
├── oauth
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20230423_1145.py
│ │ ├── 0003_auto_20230709_1237.py
│ │ └── __init__.py
│ ├── models.py
│ ├── signals.py
│ ├── templates
│ │ └── oauth
│ │ │ ├── change_profile.html
│ │ │ ├── profile.html
│ │ │ └── tags
│ │ │ └── user_avatar.html
│ ├── templatetags
│ │ ├── __init__.py
│ │ └── oauth_tags.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── portinfo
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── management
│ │ └── commands
│ │ │ ├── load_initial_data.py
│ │ │ └── ports.json
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20240615_1412.py
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── portinfo
│ │ │ ├── css
│ │ │ └── dataTables.bootstrap4.min.css
│ │ │ └── js
│ │ │ ├── dataTables.bootstrap4.min.js
│ │ │ └── dataTables.min.js
│ ├── templates
│ │ └── portinfo
│ │ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── resume
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── resume
│ │ │ └── css
│ │ │ └── detail.css
│ ├── templates
│ │ └── resume
│ │ │ ├── base.html
│ │ │ └── detail.html
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
├── rsshub
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── rsshub
│ │ │ └── rss.xml
│ ├── templatetags
│ │ └── __init__.py
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
└── tool
│ ├── __init__.py
│ ├── admin.py
│ ├── apis
│ ├── __init__.py
│ ├── bd_push.py
│ ├── common.py
│ ├── docker_search.py
│ ├── stopwords
│ │ └── ChineseStopWords.txt
│ ├── useragent.py
│ └── word_cloud.py
│ ├── apps.py
│ ├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
│ ├── models.py
│ ├── static
│ ├── editor
│ │ ├── css
│ │ │ └── editormd.min.css
│ │ ├── fonts
│ │ │ ├── FontAwesome.otf
│ │ │ ├── editormd-logo.eot
│ │ │ ├── editormd-logo.svg
│ │ │ ├── editormd-logo.ttf
│ │ │ ├── editormd-logo.woff
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.svg
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ ├── fontawesome-webfont.woff
│ │ │ └── fontawesome-webfont.woff2
│ │ ├── images
│ │ │ ├── loading.gif
│ │ │ ├── loading@2x.gif
│ │ │ └── logos
│ │ │ │ ├── editormd-favicon-16x16.ico
│ │ │ │ └── editormd-logo-96x96.png
│ │ ├── js
│ │ │ └── editormd.min.js
│ │ ├── languages
│ │ │ ├── en.js
│ │ │ └── zh-tw.js
│ │ ├── lib
│ │ │ ├── codemirror
│ │ │ │ ├── AUTHORS
│ │ │ │ ├── LICENSE
│ │ │ │ ├── README.md
│ │ │ │ ├── addon
│ │ │ │ │ ├── dialog
│ │ │ │ │ │ ├── dialog.css
│ │ │ │ │ │ └── dialog.js
│ │ │ │ │ └── search
│ │ │ │ │ │ ├── match-highlighter.js
│ │ │ │ │ │ ├── matchesonscrollbar.css
│ │ │ │ │ │ ├── matchesonscrollbar.js
│ │ │ │ │ │ ├── search.js
│ │ │ │ │ │ └── searchcursor.js
│ │ │ │ ├── addons.min.js
│ │ │ │ ├── bower.json
│ │ │ │ ├── codemirror.min.css
│ │ │ │ ├── codemirror.min.js
│ │ │ │ ├── lib
│ │ │ │ │ ├── codemirror.css
│ │ │ │ │ └── codemirror.js
│ │ │ │ ├── modes.min.js
│ │ │ │ └── package.json
│ │ │ ├── marked.min.js
│ │ │ └── prettify.min.js
│ │ └── plugins
│ │ │ ├── code-block-dialog
│ │ │ └── code-block-dialog.js
│ │ │ ├── emoji-dialog
│ │ │ ├── emoji-dialog.js
│ │ │ └── emoji.json
│ │ │ ├── goto-line-dialog
│ │ │ └── goto-line-dialog.js
│ │ │ ├── help-dialog
│ │ │ ├── help-dialog.js
│ │ │ └── help.md
│ │ │ ├── html-entities-dialog
│ │ │ ├── html-entities-dialog.js
│ │ │ └── html-entities.json
│ │ │ ├── image-dialog
│ │ │ └── image-dialog.js
│ │ │ ├── link-dialog
│ │ │ └── link-dialog.js
│ │ │ ├── preformatted-text-dialog
│ │ │ └── preformatted-text-dialog.js
│ │ │ ├── reference-link-dialog
│ │ │ └── reference-link-dialog.js
│ │ │ ├── table-dialog
│ │ │ └── table-dialog.js
│ │ │ └── test-plugin
│ │ │ └── test-plugin.js
│ └── tool
│ │ ├── css
│ │ ├── json2go
│ │ │ ├── common.css
│ │ │ └── tomorrow.highlight.css
│ │ └── tool.css
│ │ ├── img
│ │ ├── HTML5.png
│ │ ├── go.ico
│ │ ├── golang.png
│ │ ├── linux.png
│ │ ├── query_ip.png
│ │ └── tax128.png
│ │ └── js
│ │ ├── json2go
│ │ ├── common.js
│ │ ├── gofmt.js
│ │ ├── highlight.min.js
│ │ └── json-to-go.js
│ │ ├── tax
│ │ └── tax.js
│ │ └── tool.js
│ ├── templates
│ └── tool
│ │ ├── base_tool.html
│ │ ├── bd_push.html
│ │ ├── bd_push_site.html
│ │ ├── characters.html
│ │ ├── docker_search.html
│ │ ├── editor.html
│ │ ├── json2go.html
│ │ ├── linux_timeline.html
│ │ ├── query_ip.html
│ │ ├── regex.html
│ │ ├── tags
│ │ ├── github_corners.html
│ │ ├── ldt.html
│ │ ├── tool_item.html
│ │ └── tool_list.html
│ │ ├── tax.html
│ │ ├── tool.html
│ │ ├── useragent.html
│ │ └── word_cloud.html
│ ├── templatetags
│ ├── __init__.py
│ └── tool_tags.py
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
├── izone
├── __init__.py
├── celery.py
├── settings.py
├── urls.py
└── wsgi.py
├── log
└── .gitkeep
├── manage.py
├── media
├── article
│ └── default
│ │ └── default.png
├── avatar
│ └── default
│ │ ├── default.png
│ │ ├── default1.png
│ │ ├── default10.png
│ │ ├── default2.png
│ │ ├── default3.png
│ │ ├── default4.png
│ │ ├── default5.png
│ │ ├── default6.png
│ │ ├── default7.png
│ │ ├── default8.png
│ │ └── default9.png
├── friend
│ └── default
│ │ └── default.png
└── subject
│ └── default
│ └── default.png
├── requirements.txt
├── supervisord.conf
├── templates
├── 403.html
├── 404.html
├── 500.html
├── account
│ ├── account_inactive.html
│ ├── base.html
│ ├── email.html
│ ├── email
│ │ └── password_reset_key_message.txt
│ ├── email_confirm.html
│ ├── login.html
│ ├── logout.html
│ ├── password_change.html
│ ├── password_reset.html
│ ├── password_reset_done.html
│ ├── password_reset_from_key.html
│ ├── password_reset_from_key_done.html
│ ├── password_set.html
│ ├── signup.html
│ ├── signup_closed.html
│ ├── verification_sent.html
│ └── verified_email_required.html
├── admin
│ └── base.html
├── robots.txt
├── search
│ ├── blog
│ │ └── search.html
│ └── indexes
│ │ └── blog
│ │ └── article_text.txt
└── webstack
│ ├── base.html
│ └── index.html
└── utils
├── __init__.py
└── markdown_ext.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language=python
2 | *.css linguist-language=python
3 | *.html linguist-language=python
--------------------------------------------------------------------------------
/.github/workflows/dockerimage.yml:
--------------------------------------------------------------------------------
1 | name: Docker Image CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - name: Build the Docker image
13 | run: docker build -f ./Dockerfile-slim -t izone-master:$(date +%s) .
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Python template
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | env/
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *,cover
48 | .hypothesis/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 |
58 | # Flask stuff:
59 | instance/
60 | .webassets-cache
61 |
62 | # Scrapy stuff:
63 | .scrapy
64 |
65 | # Sphinx documentation
66 | docs/_build/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # Jupyter Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # celery beat schedule file
78 | celerybeat-schedule
79 |
80 | # SageMath parsed files
81 | *.sage.py
82 |
83 | # dotenv
84 | .env
85 |
86 | # virtualenv
87 | .venv
88 | venv/
89 | ENV/
90 |
91 | # Spyder project settings
92 | .spyderproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # 忽略网站个人信息,这些信息需要单独设置,不共享
98 | .idea
99 | whoosh_index/
100 | *.env
101 | # 禁用上传目录
102 | upload/
103 |
104 | # jieba
105 | .DS_Store
106 |
107 | # celery
108 | *.pid
109 |
110 | # templates test html
111 | templates/test*.html
112 |
113 | # log
114 | log/*.log*
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9
2 |
3 | # 国内用户构建命令参考
4 | # DOCKER_BUILDKIT=0 docker build --build-arg pip_index_url=http://mirrors.aliyun.com/pypi/simple/ --build-arg pip_trusted_host=mirrors.aliyun.com -t hopetree/izone:lts .
5 |
6 | ARG pip_index_url=https://pypi.org/simple
7 | ARG pip_trusted_host=pypi.org
8 | ENV PYTHONUNBUFFERED=1
9 | WORKDIR /opt/cloud/izone
10 |
11 | RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
12 | COPY requirements.txt requirements.txt
13 | RUN pip install --no-cache-dir setuptools==68.0.0 --index-url $pip_index_url --trusted-host $pip_trusted_host
14 | RUN pip install --no-cache-dir -r requirements.txt --index-url $pip_index_url --trusted-host $pip_trusted_host
15 | RUN mkdir -p log && chmod -R 755 log
16 |
17 | COPY . .
18 |
19 | # 设置镜像的创建时间,当做网站更新时间
20 | RUN sed -i "s/web_update_time=\"\"/web_update_time=\"$(date +'%Y-%m-%d %H:%M')\"/g" ./apps/blog/templates/blog/base.html
21 |
22 | CMD ["supervisord", "-n", "-c", "supervisord.conf"]
23 |
--------------------------------------------------------------------------------
/Dockerfile-slim:
--------------------------------------------------------------------------------
1 | FROM python:3.9-slim
2 |
3 | # 国内用户构建命令参考
4 | # DOCKER_BUILDKIT=0 docker build --build-arg pip_index_url=http://mirrors.aliyun.com/pypi/simple/ --build-arg pip_trusted_host=mirrors.aliyun.com --build-arg debian_host=mirrors.ustc.edu.cn -f Dockerfile-slim -t hopetree/izone:lts .
5 |
6 | # 默认的系统源和pypi源都使用国外的,国内构建的时候可以用命令行参数替换成国内源
7 | ARG debian_host=deb.debian.org
8 | ARG pip_index_url=https://pypi.org/simple
9 | ARG pip_trusted_host=pypi.org
10 |
11 |
12 | ENV PYTHONUNBUFFERED=1
13 | WORKDIR /opt/cloud/izone
14 |
15 | # 替换系统源,要注意这里不同版本的debian源文件不同
16 | RUN sed -i "s/deb.debian.org/${debian_host}/g" /etc/apt/sources.list.d/debian.sources
17 |
18 | # 安装sqlclient的依赖,slim镜像中缺少
19 | RUN apt-get update && apt-get install -y \
20 | default-libmysqlclient-dev \
21 | build-essential \
22 | && rm -rf /var/lib/apt/lists/*
23 |
24 | RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
25 | COPY requirements.txt requirements.txt
26 | RUN pip install --no-cache-dir setuptools==68.0.0 --index-url $pip_index_url --trusted-host $pip_trusted_host
27 | RUN pip install --no-cache-dir -r requirements.txt --index-url $pip_index_url --trusted-host $pip_trusted_host
28 | RUN mkdir -p log && chmod -R 755 log
29 |
30 | COPY . .
31 |
32 | # 设置镜像的创建时间,当做网站更新时间
33 | RUN sed -i "s/web_update_time=\"\"/web_update_time=\"$(date +'%Y-%m-%d %H:%M')\"/g" ./apps/blog/templates/blog/base.html
34 |
35 | CMD ["supervisord", "-n", "-c", "supervisord.conf"]
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Hopetree
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 一个以 Django 作为框架搭建的个人博客。
2 |
3 | 博客效果: https://tendcode.com/
4 |
5 | ## 功能介绍
6 | - Django 自带的后台管理系统,方便对于文章、用户及其他动态内容的管理
7 | - 文章分类、标签、浏览量统计以及规范的 SEO 设置
8 | - 用户认证系统,在 Django 自带的用户系统的基础上扩展 Oauth 认证,支持微博、Github 等第三方认证
9 | - 文章评论系统,炫酷的输入框特效,支持 markdown 语法,二级评论结构和回复功能
10 | - 信息提醒功能,登录和退出提醒,收到评论和回复提醒,信息管理
11 | - 强大的全文搜索功能,只需要输入关键词就能展现全站与之关联的文章
12 | - RSS 博客订阅功能及规范的 Sitemap 网站地图
13 | - 实用的在线工具
14 | - 友情链接和推荐工具网站的展示
15 | - 缓存系统,遵循缓存原则,加速网站打开速度
16 | - RESTful API 风格的 API 接口
17 |
18 | ## 博客页面效果(响应式)
19 | - PC 页面效果
20 |
21 | 
22 |
23 | - PC 暗色主题效果
24 |
25 | 
26 |
27 | - PC 文章详情页,左边显示专题目录,右边显示文章目录,支持代码高亮
28 |
29 | 
30 |
31 | - PC 专题页,按文章归类
32 |
33 | 
34 |
35 | - 云监控服务,提供服务器的监控能力,客户端提供 Golang 版本,也可以自行编写 Python 版本的客户端用来上报数据
36 |
37 | 
38 |
39 | - PC 友情链接页,定时任务自动校验网址有效性
40 |
41 | 
42 |
43 | - PC 在线工具,平台自带工具
44 |
45 | 
46 |
47 | - ipad 效果
48 |
49 | 
50 |
51 | - 手机效果
52 |
53 | 
54 |
55 | ## 运行指导
56 | - 由于本项目分为几个不同的分支,每个分支的功能是一样的,但是运行的方式不同,所以需要根据分支查看对应的运行wiki
57 | - 指导 wiki:https://github.com/Hopetree/izone/wiki
58 | - 部署指导完整步骤:https://tendcode.com/subject/article/izone-install-docs/
59 |
--------------------------------------------------------------------------------
/apps/api/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
/apps/api/permissions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import permissions
3 |
4 |
5 | class IsAdminUserOrReadOnly(permissions.BasePermission):
6 | def has_permission(self, request, view):
7 | if request.method in permissions.SAFE_METHODS:
8 | return True
9 | return request.user and request.user.is_staff
--------------------------------------------------------------------------------
/apps/api/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from oauth.models import Ouser
3 | from rest_framework import serializers
4 | from blog.models import Article, Tag, Category, Timeline
5 | from tool.models import ToolLink, ToolCategory
6 |
7 |
8 | class UserSerializer(serializers.ModelSerializer):
9 | class Meta:
10 | model = Ouser
11 | fields = ('id', 'username', 'first_name', 'link', 'avatar')
12 | # fields = '__all__'
13 | # exclude = ('password','email')
14 |
15 |
16 | class TagSerializer(serializers.ModelSerializer):
17 | class Meta:
18 | model = Tag
19 | fields = '__all__'
20 |
21 |
22 | class CategorySerializer(serializers.ModelSerializer):
23 | class Meta:
24 | model = Category
25 | fields = '__all__'
26 |
27 |
28 | class ArticleSerializer(serializers.ModelSerializer):
29 | author = serializers.ReadOnlyField(source='author.username')
30 | category = CategorySerializer(read_only=True)
31 | tags = TagSerializer(
32 | many=True,
33 | read_only=True,
34 | )
35 | keywords = serializers.SlugRelatedField(
36 | many=True,
37 | read_only=True,
38 | slug_field='name'
39 | )
40 |
41 | class Meta:
42 | model = Article
43 | # fields = ('id', 'author', 'title', 'views', 'category', 'tags')
44 | # fields = '__all__'
45 | exclude = ('body',)
46 |
47 |
48 | class TimelineSerializer(serializers.ModelSerializer):
49 | class Meta:
50 | model = Timeline
51 | fields = '__all__'
52 |
53 |
54 | class ToolCategorySerializer(serializers.ModelSerializer):
55 | class Meta:
56 | model = ToolCategory
57 | fields = '__all__'
58 |
59 |
60 | class ToolLinkSerializer(serializers.ModelSerializer):
61 | category = ToolCategorySerializer()
62 |
63 | class Meta:
64 | model = ToolLink
65 | fields = '__all__'
66 |
--------------------------------------------------------------------------------
/apps/api/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | # @Date : 2019/2/1
3 |
4 | from rest_framework.routers import DefaultRouter
5 | from .views import (UserListSet, ArticleListSet, TagListSet,
6 | CategoryListSet, TimelineListSet, ToolLinkListSet)
7 |
8 | router = DefaultRouter()
9 | router.register(r'users', UserListSet)
10 | router.register(r'articles', ArticleListSet)
11 | router.register(r'tags', TagListSet)
12 | router.register(r'categorys', CategoryListSet)
13 | router.register(r'timelines', TimelineListSet)
14 | router.register(r'toollinks', ToolLinkListSet)
15 |
--------------------------------------------------------------------------------
/apps/api/views.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | from oauth.models import Ouser
5 | from blog.models import Article, Tag, Category, Timeline
6 | from tool.models import ToolLink
7 | from .serializers import (UserSerializer, ArticleSerializer,
8 | TimelineSerializer,TagSerializer,CategorySerializer,ToolLinkSerializer)
9 | from rest_framework import viewsets, permissions
10 | from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
11 | # from .permissions import IsAdminUserOrReadOnly
12 |
13 | # RESEful API VIEWS
14 | class UserListSet(viewsets.ModelViewSet):
15 | queryset = Ouser.objects.all()
16 | serializer_class = UserSerializer
17 | permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)
18 |
19 | class ArticleListSet(viewsets.ModelViewSet):
20 | queryset = Article.objects.all()
21 | serializer_class = ArticleSerializer
22 | permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)
23 |
24 | def perform_create(self,serializer):
25 | serializer.save(author=self.request.user)
26 |
27 | class TagListSet(viewsets.ModelViewSet):
28 | queryset = Tag.objects.all()
29 | serializer_class = TagSerializer
30 | permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)
31 |
32 | class CategoryListSet(viewsets.ModelViewSet):
33 | queryset = Category.objects.all()
34 | serializer_class = CategorySerializer
35 | permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)
36 |
37 | class TimelineListSet(viewsets.ModelViewSet):
38 | queryset = Timeline.objects.all()
39 | serializer_class = TimelineSerializer
40 | permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)
41 |
42 | class ToolLinkListSet(viewsets.ModelViewSet):
43 | queryset = ToolLink.objects.all()
44 | serializer_class = ToolLinkSerializer
45 | permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)
--------------------------------------------------------------------------------
/apps/blog/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'blog.apps.BlogConfig'
--------------------------------------------------------------------------------
/apps/blog/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class BlogConfig(AppConfig):
5 | name = 'blog'
6 | verbose_name = '博客管理'
7 |
8 | def ready(self):
9 | from . import signals # 导入信号处理程序模块
10 |
--------------------------------------------------------------------------------
/apps/blog/context_processors.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import datetime
3 | import json
4 | from django.conf import settings
5 | from .utils import (site_full_url, get_site_create_day)
6 |
7 | # 静态文件版本(只收集常改的,不常改的直接在页面改),每次更新了静态文件就更新一下这个版本
8 | # todo 可以做成自动化,每次拉git代码的时候检查是否更新了某个静态文件,自动更新版本
9 | STATIC_VERSION = {
10 | 'css_blog_base': '20240305.02',
11 | 'css_blog_detail': '20240324.01',
12 | 'css_blog_night': '20240615.01',
13 |
14 | 'js_blog_base': '20240305.01',
15 | 'js_blog_article': '20240115.01',
16 | 'js_blog_code': '20240129.02',
17 |
18 | 'css_tool_tool': '20240115.01',
19 | 'js_tool_tool': '20240115.01',
20 | }
21 |
22 |
23 | # 自定义上下文管理器
24 | def settings_info(request):
25 | site_create_day = get_site_create_day(settings.SITE_CREATE_DATE)
26 | return {
27 | 'this_year': datetime.datetime.now().year,
28 | 'site_create_date': site_create_day[0],
29 | 'site_create_year': site_create_day[1],
30 | 'site_logo_name': settings.SITE_LOGO_NAME,
31 | 'site_end_title': settings.SITE_END_TITLE,
32 | 'site_description': settings.SITE_DESCRIPTION,
33 | 'site_keywords': settings.SITE_KEYWORDS,
34 | 'tool_flag': settings.TOOL_FLAG,
35 | 'api_flag': settings.API_FLAG,
36 | 'cnzz_protocol': settings.CNZZ_PROTOCOL,
37 | '51la': settings.LA51_PROTOCOL,
38 | 'beian': settings.BEIAN,
39 | 'my_github': settings.MY_GITHUB,
40 | 'site_verification': settings.MY_SITE_VERIFICATION,
41 | 'site_url': site_full_url(),
42 | 'static_version': STATIC_VERSION,
43 | }
44 |
--------------------------------------------------------------------------------
/apps/blog/feeds.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from xml.sax.saxutils import escape
3 | from django.contrib.syndication.views import Feed
4 | from .models import Article
5 | from django.conf import settings
6 |
7 |
8 | class AllArticleRssFeed(Feed):
9 | # 显示在聚会阅读器上的标题
10 | title = settings.SITE_END_TITLE
11 | # 跳转网址,为主页
12 | link = "/"
13 | # 描述内容
14 | description = settings.SITE_DESCRIPTION
15 |
16 | # 需要显示的内容条目,这个可以自己挑选一些热门或者最新的博客
17 | def items(self):
18 | return Article.objects.filter(is_publish=True)[:10]
19 |
20 | # 显示的内容的标题,这个才是最主要的东西
21 | def item_title(self, item):
22 | return item.title
23 |
24 | # 显示的内容的描述
25 | def item_description(self, item):
26 | return item.body_to_markdown()
27 |
--------------------------------------------------------------------------------
/apps/blog/management/commands/clear_cache.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | from django.core.management.base import BaseCommand
3 | from django.core.cache import cache
4 |
5 |
6 | class Command(BaseCommand):
7 | help = 'Clears cache for specified keys or clears keys like views.*.statistics.* if none provided'
8 |
9 | def add_arguments(self, parser):
10 | parser.add_argument('keys', nargs='*', type=str, help='Keys to clear from cache')
11 |
12 | def handle(self, *args, **options):
13 | keys_to_clear = options['keys']
14 |
15 | if not keys_to_clear:
16 | # If no keys provided, clear keys matching the pattern
17 | keys_matching_pattern = cache.keys('views.*.statistics.*')
18 |
19 | if keys_matching_pattern:
20 | for key in keys_matching_pattern:
21 | cache.delete(key)
22 | self.stdout.write(
23 | self.style.SUCCESS(f'Cache cleared successfully for key: {key}'))
24 | else:
25 | self.stdout.write(self.style.SUCCESS('No matching keys found to clear'))
26 | else:
27 | # Clear cache for each specified key
28 | for key in keys_to_clear:
29 | cache.delete(key)
30 | self.stdout.write(self.style.SUCCESS(f'Cache cleared successfully for key: {key}'))
31 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0002_article_is_publish.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-06-30 13:54
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='article',
15 | name='is_publish',
16 | field=models.BooleanField(default=True, verbose_name='是否发布'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0003_auto_20230702_1043.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-02 10:43
2 |
3 | from django.db import migrations
4 | import imagekit.models.fields
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('blog', '0002_article_is_publish'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='friendlink',
16 | name='logo',
17 | field=imagekit.models.fields.ProcessedImageField(blank=True, default='friend/default.png', upload_to='friend/%Y/%m/%d', verbose_name='网站LOGO'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0004_auto_20230702_1134.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-02 11:34
2 |
3 | from django.db import migrations
4 | import imagekit.models.fields
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('blog', '0003_auto_20230702_1043'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='friendlink',
16 | name='logo',
17 | field=imagekit.models.fields.ProcessedImageField(blank=True, default='friend/default.png', help_text='上传图片大小建议120x120以上,使用友联域名命名,如tendcode.com.png', upload_to='friend/%Y', verbose_name='网站LOGO'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0005_auto_20230702_1623.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-02 16:23
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0004_auto_20230702_1134'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='friendlink',
15 | name='not_show_reason',
16 | field=models.CharField(blank=True, max_length=50, null=True, verbose_name='禁用原因'),
17 | ),
18 | migrations.AlterField(
19 | model_name='friendlink',
20 | name='is_show',
21 | field=models.BooleanField(default=False, verbose_name='是否展示'),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0006_auto_20230708_0641.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-08 06:41
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0005_auto_20230702_1623'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterModelOptions(
14 | name='timeline',
15 | options={'ordering': ['-update_date'], 'verbose_name': '时间线', 'verbose_name_plural': '时间线'},
16 | ),
17 | ]
18 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0007_auto_20230709_1237.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-09 12:37
2 |
3 | from django.db import migrations
4 | import imagekit.models.fields
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('blog', '0006_auto_20230708_0641'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='friendlink',
16 | name='logo',
17 | field=imagekit.models.fields.ProcessedImageField(blank=True, default='friend/default/default.png', help_text='上传图片大小建议120x120以上,使用友联域名命名,如tendcode.com.png', upload_to='friend/upload/%Y', verbose_name='网站LOGO'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0008_auto_20230710_1613.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-10 16:13
2 |
3 | from django.db import migrations
4 | import imagekit.models.fields
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('blog', '0007_auto_20230709_1237'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='article',
16 | name='img_link',
17 | field=imagekit.models.fields.ProcessedImageField(blank=True, default='article/default/default.png', help_text='上传图片大小建议使用5:3的宽高比,为了清晰度原始图片宽度应该超过250px', upload_to='article/upload/%Y/%m/%d/', verbose_name='封面图'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0009_auto_20230713_1223.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-13 12:23
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0008_auto_20230710_1613'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='category',
15 | name='description',
16 | field=models.TextField(default='分类描述', help_text='用来作为SEO中description,长度参考SEO标准', max_length=240, verbose_name='描述'),
17 | ),
18 | migrations.AlterField(
19 | model_name='tag',
20 | name='description',
21 | field=models.TextField(default='标签描述', help_text='用来作为SEO中description,长度参考SEO标准', max_length=240, verbose_name='描述'),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0011_auto_20230715_1443.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-15 14:43
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0010_auto_20230715_1407'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='article',
15 | name='topic_short_title',
16 | field=models.CharField(blank=True, help_text='专门给Topic使用的短标题', max_length=50, null=True, verbose_name='主题短标题'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0012_auto_20230727_1929.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-27 19:29
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0011_auto_20230715_1443'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterModelOptions(
14 | name='subject',
15 | options={'ordering': ['sort_order'], 'verbose_name': '专题', 'verbose_name_plural': '专题'},
16 | ),
17 | migrations.AlterModelOptions(
18 | name='topic',
19 | options={'ordering': ['sort_order'], 'verbose_name': '专题-主题', 'verbose_name_plural': '专题-主题'},
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0013_articleview.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-12-08 12:55
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0012_auto_20230727_1929'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='ArticleView',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('date', models.CharField(max_length=10, verbose_name='统计日期')),
18 | ('body', models.TextField(verbose_name='统计数据')),
19 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='录入时间')),
20 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
21 | ],
22 | options={
23 | 'verbose_name': '文章浏览量统计',
24 | 'verbose_name_plural': '文章浏览量统计',
25 | 'ordering': ['create_date'],
26 | },
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0014_auto_20231208_1310.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-12-08 13:10
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0013_articleview'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='articleview',
15 | name='date',
16 | field=models.CharField(max_length=10, unique=True, verbose_name='统计日期'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0015_pageview.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-12-13 11:20
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0014_auto_20231208_1310'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='PageView',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('url', models.CharField(max_length=255, unique=True, verbose_name='页面地址')),
18 | ('name', models.CharField(blank=True, max_length=255, null=True, verbose_name='页面名称')),
19 | ('views', models.IntegerField(default=0, verbose_name='浏览量')),
20 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='录入时间')),
21 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
22 | ],
23 | options={
24 | 'verbose_name': '单页面浏览量',
25 | 'verbose_name_plural': '单页面浏览量',
26 | 'ordering': ['url'],
27 | },
28 | ),
29 | ]
30 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0016_pageview_is_compute.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-12-14 15:43
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0015_pageview'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='pageview',
15 | name='is_compute',
16 | field=models.BooleanField(default=True, verbose_name='是否计算到访问量'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0017_feedhub.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-01-01 17:17
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0016_pageview_is_compute'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='FeedHub',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('name', models.CharField(max_length=50, unique=True, verbose_name='名称')),
18 | ('url', models.CharField(max_length=255, verbose_name='feed地址')),
19 | ('icon', models.TextField(help_text='可以填写base64图片格式或者图标地址', verbose_name='图标地址')),
20 | ('is_active', models.BooleanField(default=True, help_text='作为是否采集的标识', verbose_name='是否有效')),
21 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='录入时间')),
22 | ('data', models.TextField(blank=True, help_text='定义任务采集数据', null=True, verbose_name='数据')),
23 | ],
24 | options={
25 | 'verbose_name': 'Feed Hub',
26 | 'verbose_name_plural': 'Feed Hub',
27 | 'ordering': ['name'],
28 | },
29 | ),
30 | ]
31 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0018_auto_20240101_1903.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-01-01 19:03
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0017_feedhub'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterModelOptions(
14 | name='feedhub',
15 | options={'ordering': ['sort_order'], 'verbose_name': 'Feed Hub', 'verbose_name_plural': 'Feed Hub'},
16 | ),
17 | migrations.AddField(
18 | model_name='feedhub',
19 | name='sort_order',
20 | field=models.IntegerField(default=99, help_text='作为显示的时候的顺序', verbose_name='排序'),
21 | ),
22 | ]
23 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0019_menulink.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-03-26 09:25
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0018_auto_20240101_1903'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='MenuLink',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('name', models.CharField(help_text='如:Github 主页', max_length=20, unique=True, verbose_name='名称')),
18 | ('icon', models.CharField(help_text='如:fa-github', max_length=20, unique=True, verbose_name='图标')),
19 | ('link', models.CharField(max_length=200, unique=True, verbose_name='链接')),
20 | ('title', models.CharField(help_text='外链的描述', max_length=50, unique=True, verbose_name='标题')),
21 | ('active', models.BooleanField(default=True, help_text='是展示有效的链接', verbose_name='是否有效')),
22 | ('sort_order', models.IntegerField(default=99, help_text='作为显示的时候的顺序', verbose_name='排序')),
23 | ],
24 | options={
25 | 'verbose_name': '菜单外链',
26 | 'verbose_name_plural': '菜单外链',
27 | 'ordering': ['sort_order'],
28 | },
29 | ),
30 | ]
31 |
--------------------------------------------------------------------------------
/apps/blog/migrations/0020_auto_20240409_1309.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-04-09 13:09
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('blog', '0019_menulink'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='carousel',
15 | name='content',
16 | field=models.CharField(blank=True, max_length=80, null=True, verbose_name='描述'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/blog/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/blog/search_indexes.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from haystack import indexes
4 | from .models import Article
5 |
6 |
7 | class ArticleIndex(indexes.SearchIndex, indexes.Indexable):
8 | text = indexes.CharField(document=True, use_template=True)
9 | views = indexes.IntegerField(model_attr='views')
10 | # 添加这个字段,可以在查询的时候作为过滤条件,如果不添加则不能用来过滤,新增字段要重新生成索引
11 | is_publish = indexes.BooleanField(model_attr='is_publish')
12 |
13 | def get_model(self):
14 | return Article
15 |
16 | def index_queryset(self, using=None):
17 | return self.get_model().objects.all()
18 |
--------------------------------------------------------------------------------
/apps/blog/signals.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.dispatch import receiver
3 | from django.db.models.signals import post_save
4 | from django.urls import reverse
5 |
6 | from .models import FriendLink
7 | from comment.models import SystemNotification
8 | from oauth.models import Ouser
9 |
10 |
11 | @receiver(post_save, sender=FriendLink)
12 | def friend_link_create_signal(sender, instance, created, **kwargs):
13 | """
14 | 创建新的友情链接则自带给管理员推送审核消息
15 | @param sender:
16 | @param instance:
17 | @param created:
18 | @param kwargs:
19 | @return:
20 | """
21 | # 判断是否是第一次生成
22 | if created:
23 | superuser = Ouser.objects.filter(is_superuser=True)
24 | title = f'增加一个新的{instance._meta.verbose_name}:{instance.name}'
25 | admin_url = reverse('admin:blog_friendlink_change', args=[instance.id])
26 | content = f'
友链地址:{instance.link},' \
27 | f'描述:{instance.description},待管理员审核!!!
'
28 | new_notify = SystemNotification(title=title, content=content)
29 | new_notify.save() # 保存实例
30 |
31 | # 在保存实例后,将关联对象添加到多对多关系中
32 | new_notify.get_p.set(superuser)
33 |
--------------------------------------------------------------------------------
/apps/blog/sitemaps.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.contrib.sitemaps import Sitemap
3 | from .models import Article, Category, Tag
4 | from django.db.models.aggregates import Count
5 | from .utils import site_protocol
6 |
7 |
8 | class MySitemap(Sitemap):
9 | protocol = site_protocol()
10 |
11 |
12 | class ArticleSitemap(MySitemap):
13 | changefreq = 'weekly'
14 | priority = 1.0
15 |
16 | def items(self):
17 | return Article.objects.filter(is_publish=True)
18 |
19 | def lastmod(self, obj):
20 | return obj.update_date
21 |
22 |
23 | class CategorySitemap(MySitemap):
24 | changefreq = 'weekly'
25 | priority = 0.8
26 |
27 | def items(self):
28 | return Category.objects.filter(article__is_publish=True).annotate(
29 | total_num=Count('article')).filter(total_num__gt=0)
30 |
31 | def lastmod(self, obj):
32 | return obj.article_set.first().create_date
33 |
34 |
35 | class TagSitemap(MySitemap):
36 | changefreq = 'weekly'
37 | priority = 0.8
38 |
39 | def items(self):
40 | return Tag.objects.filter(article__is_publish=True).annotate(
41 | total_num=Count('article')).filter(total_num__gt=0)
42 |
43 | def lastmod(self, obj):
44 | return obj.article_set.first().create_date
45 |
--------------------------------------------------------------------------------
/apps/blog/static/blog/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/apps/blog/static/blog/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/apps/blog/static/blog/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/apps/blog/static/blog/css/account.css:
--------------------------------------------------------------------------------
1 | .secondaryAction{color:#868e96;}.secondaryAction:hover{text-decoration:none;color:#007bff;}.asteriskField{margin-left:.25rem;color:#dc3545;}#social-login .login-title{position:relative;display:block;margin-bottom:10px;}#social-login span{color:#999;}#social-login span:before,#social-login span:after{position:absolute;top:50%;background:#eee;width:38%;height:1px;content:'';}#social-login span:before{left:0;}#social-login span:after{right:0;}.fa-weibo{color:#e12f11;opacity:.8;}.fa-github{color:#333;opacity:.8;}.fa-weibo:hover,.fa-github:hover{opacity:1;}.btn-sm{padding:.2rem .7rem;}.change_profile .form-control,.card-login .form-control{border-radius:0;}.change_profile .alert,.card-login .alert{border-radius:0;}.change_profile .alert li,.card-login .alert li{margin-bottom:.5rem;}.change_profile .alert ul,.card-login .alert ul{padding-left:.5rem;margin-bottom:0;}#profile-avatar .avatar{width:80px;padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;}
--------------------------------------------------------------------------------
/apps/blog/static/blog/css/monokai.css:
--------------------------------------------------------------------------------
1 | .codehilite pre{font-size:85%;padding:.5rem;color:#A6ACCD;}.codehilite{background:#292b30;color:#A6ACCD;border-radius:8px;}.codehilite .hll{background-color:#49483e}.codehilite .c{color:#676E95}.codehilite .err{color:#960050;background-color:#1e0010}.codehilite .k{color:#89DDFF}.codehilite .l{color:#ae81ff}.codehilite .n{color:#A6ACCD}.codehilite .o{color:#f92672}.codehilite .p{color:#A6ACCD}.codehilite .ch{color:#676E95}.codehilite .cm{color:#676E95}.codehilite .cp{color:#676E95}.codehilite .cpf{color:#676E95}.codehilite .c1{color:#676E95}.codehilite .cs{color:#676E95}.codehilite .gd{color:#f92672}.codehilite .ge{font-style:italic}.codehilite .gi{color:#a6e22e}.codehilite .gs{font-weight:bold}.codehilite .gu{color:#676E95}.codehilite .kc{color:#89DDFF}.codehilite .kd{color:#89DDFF}.codehilite .kn{color:#f92672}.codehilite .kp{color:#89DDFF}.codehilite .kr{color:#89DDFF}.codehilite .kt{color:#89DDFF}.codehilite .ld{color:#C3E88D}.codehilite .m{color:#ae81ff}.codehilite .s{color:#C3E88D}.codehilite .na{color:#a6e22e}.codehilite .nb{color:#A6ACCD}.codehilite .nc{color:#a6e22e}.codehilite .no{color:#89DDFF}.codehilite .nd{color:#a6e22e}.codehilite .ni{color:#A6ACCD}.codehilite .ne{color:#a6e22e}.codehilite .nf{color:#a6e22e}.codehilite .nl{color:#A6ACCD}.codehilite .nn{color:#A6ACCD}.codehilite .nx{color:#a6e22e}.codehilite .py{color:#A6ACCD}.codehilite .nt{color:#f92672}.codehilite .nv{color:#A6ACCD}.codehilite .ow{color:#f92672}.codehilite .w{color:#A6ACCD}.codehilite .mb{color:#ae81ff}.codehilite .mf{color:#ae81ff}.codehilite .mh{color:#ae81ff}.codehilite .mi{color:#ae81ff}.codehilite .mo{color:#ae81ff}.codehilite .sa{color:#C3E88D}.codehilite .sb{color:#C3E88D}.codehilite .sc{color:#C3E88D}.codehilite .dl{color:#C3E88D}.codehilite .sd{color:#C3E88D}.codehilite .s2{color:#C3E88D}.codehilite .se{color:#ae81ff}.codehilite .sh{color:#C3E88D}.codehilite .si{color:#C3E88D}.codehilite .sx{color:#C3E88D}.codehilite .sr{color:#C3E88D}.codehilite .s1{color:#C3E88D}.codehilite .ss{color:#C3E88D}.codehilite .bp{color:#A6ACCD}.codehilite .fm{color:#a6e22e}.codehilite .vc{color:#A6ACCD}.codehilite .vg{color:#A6ACCD}.codehilite .vi{color:#A6ACCD}.codehilite .vm{color:#A6ACCD}.codehilite .il{color:#ae81ff}
--------------------------------------------------------------------------------
/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/404.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/TOP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/TOP.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/baidu-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/baidu-2.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/blog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/blog.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/chrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/chrome.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/docker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/docker.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/favicon.ico
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/friend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/friend.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/github.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/html.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/map.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/nav-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/nav-logo.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/regex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/regex.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/reward_wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/reward_wx.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/reward_zfb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/reward_zfb.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/rss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/rss.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/summary.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/toggle-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/toggle-dark.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/toggle-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/toggle-light.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/img/word-cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/blog/static/blog/img/word-cloud.png
--------------------------------------------------------------------------------
/apps/blog/static/blog/js/js.cookie.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Minified by jsDelivr using Terser v3.14.1.
3 | * Original file: /npm/js-cookie@2.2.1/src/js.cookie.js
4 | *
5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
6 | */
7 | !function(e){var n;if("function"==typeof define&&define.amd&&(define(e),n=!0),"object"==typeof exports&&(module.exports=e(),n=!0),!n){var t=window.Cookies,o=window.Cookies=e();o.noConflict=function(){return window.Cookies=t,o}}}(function(){function e(){for(var e=0,n={};e
8 |
9 | {% endblock %}
10 | {% block top-file %}
11 |
16 | {% endblock %}
17 |
18 |
19 | {% block base_content %}
20 |
21 |
22 |
23 |
{{ body|safe }}
24 |
25 |
26 | {% include 'blog/tags/base_right.html' %}
27 |
28 |
29 |
30 | {% endblock %}
--------------------------------------------------------------------------------
/apps/blog/templates/blog/index.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 | {% load humanize %}
4 | {% load blog_tags %}
5 | {% load tctip_tags %}
6 |
7 | {% block head_title %}Tend to Code_一个使用django和bootstrap搭建的个人博客{% endblock %}
8 | {% block metas %}
9 |
10 |
11 |
12 | {% if site_verification %}{{ site_verification|safe }}{% endif %}
13 | {% endblock %}
14 |
15 | {% block top-file %}{% load_tctip %}{% endblock %}
16 |
17 | {% block base_content %}
18 |
19 |
20 |
21 | {% include 'blog/tags/carousel.html' %}
22 |
23 |
24 | 时间排序
25 |
27 | 热度排序
28 |
31 |
32 | {% load_article_summary articles user %}
33 | {% if is_paginated %}
34 |
{% load_pages 10 %}
35 |
{% load_pages 4 %}
36 | {% endif %}
37 |
38 |
39 | {% include 'blog/tags/base_right.html' %}
40 |
41 |
42 |
43 | {% endblock %}
--------------------------------------------------------------------------------
/apps/blog/templates/blog/silian.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% for each in badurls %}
4 |
5 | {{ each.badurl }}
6 |
7 | {% endfor %}
8 |
--------------------------------------------------------------------------------
/apps/blog/templates/blog/subjectIndex.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 | {% load blog_tags %}
4 |
5 | {% block head_title %}专题{% endblock %}
6 | {% block metas %}
7 |
8 |
9 | {% endblock %}
10 |
11 | {% block base_content %}
12 |
13 |
14 | {% for subject in subjects %}
15 |
33 | {% endfor %}
34 |
35 |
36 | {% endblock %}
37 |
38 |
--------------------------------------------------------------------------------
/apps/blog/templates/blog/tags/carousel.html:
--------------------------------------------------------------------------------
1 | {% load static blog_tags %}
2 | {% get_carousel_list as carousels %}
3 |
4 |
5 | {% for each in carousels %}
6 | {% if forloop.counter0 == 0 %}
7 |
8 | {% else %}
9 |
10 | {% endif %}
11 | {% endfor %}
12 |
13 |
--------------------------------------------------------------------------------
/apps/blog/templates/blog/tags/menulink.html:
--------------------------------------------------------------------------------
1 | {% load blog_tags %}
2 | {% if private_links %}
3 |
4 | 个人外链
9 |
17 |
18 | {% endif %}
--------------------------------------------------------------------------------
/apps/blog/templates/blog/tags/pagecut.html:
--------------------------------------------------------------------------------
1 | {% load blog_tags %}
2 |
3 | {% if page_obj.has_previous %}
4 | {% deal_with_full_path request.get_full_path 'page' page_obj.previous_page_number as new_pre_page_path %}
5 |
上一页
6 | {% endif %}
7 | {% for page in page_range %}
8 | {% if page_obj.number == page %}
9 |
{{ page }}
10 | {% elif page == "..." %}
11 |
{{ page }}
12 | {% else %}
13 | {% deal_with_full_path request.get_full_path 'page' page as page_path %}
14 |
{{ page }}
15 | {% endif %}
16 | {% endfor %}
17 | {% if page_obj.has_next %}
18 | {% deal_with_full_path request.get_full_path 'page' page_obj.next_page_number as new_next_page_path %}
19 |
下一页
20 | {% endif %}
21 |
22 |
--------------------------------------------------------------------------------
/apps/blog/templates/blog/tags/reward.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
6 |
7 | 如果文章对你有所帮助,可以赞助本站
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/apps/blog/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
/apps/blog/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 | import datetime
3 |
4 | # Create your tests here.
5 |
6 | from django.urls import reverse
7 |
8 |
9 | class ArticleAdminUrlTestCase(TestCase):
10 |
11 | def test_edit_blog_url(self):
12 | change_url = reverse('admin:blog_article_change', args=[61])
13 | self.assertEqual('/adminx/blog/article/61/change/', change_url)
14 |
--------------------------------------------------------------------------------
/apps/blog/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.urls import path
3 | from django.conf import settings
4 | from .views import test_page_view
5 | from .views import (IndexView, DetailView, CategoryView, TagView, AboutView,
6 | SilianView, MySearchView, ArchiveView, TimelineView, DetailEditView,
7 | update_article, FriendLinkView, friend_add, SubjectDetailView,
8 | SubjectPageDetailView, SubjectListView, dashboard, feed_hub)
9 |
10 | urlpatterns = [
11 | path('', IndexView.as_view(), name='index'), # 主页,自然排序
12 | path('article/
/', DetailView.as_view(), name='detail'), # 文章内容页
13 | path('article-edit//', DetailEditView.as_view(), name='article_edit'), # 文章编辑
14 | path('article-update/', update_article, name='article_update'), # 文章更新
15 | path('category//', CategoryView.as_view(), name='category'),
16 | path('tag//', TagView.as_view(), name='tag'),
17 | path('about/', AboutView, name='about'), # About页面
18 | path('timeline/', TimelineView.as_view(), name='timeline'), # timeline页面
19 | path('archive/', ArchiveView.as_view(), name='archive'), # 归档页面
20 | path('silian.xml', SilianView.as_view(content_type='application/xml'), name='silian'), # 死链页面
21 | path('search/', MySearchView.as_view(), name='search_view'), # 全文搜索
22 | path('friend/', FriendLinkView.as_view(), name='friend'), # 友情链接
23 | path('friend/add/', friend_add, name='friend_add'), # 友情链接申请
24 | path('dashboard/', dashboard, name='dashboard'), # 看板
25 | path('feed-hub/', feed_hub, name='feedhub'), # feed hub
26 |
27 | # 专题列表页
28 | path('subject/', SubjectListView.as_view(), name='subject_index'),
29 | # 专题详情页
30 | path('subject//', SubjectPageDetailView.as_view(), name='subject_page'),
31 | # 专题文章内容页
32 | path('subject/article//', SubjectDetailView.as_view(), name='subject_detail'),
33 |
34 | ]
35 |
36 | if settings.DEBUG:
37 | urlpatterns.append(path('test/', test_page_view, name='test'))
38 |
--------------------------------------------------------------------------------
/apps/comment/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'comment.apps.CommentConfig'
--------------------------------------------------------------------------------
/apps/comment/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import (ArticleComment, Notification, SystemNotification)
3 |
4 |
5 | @admin.register(ArticleComment)
6 | class CommentAdmin(admin.ModelAdmin):
7 | date_hierarchy = 'create_date'
8 | list_display = ('id', 'author', 'belong', 'create_date', 'show_content')
9 | list_filter = ('author', 'belong',)
10 | ordering = ('-id',)
11 | # 设置需要添加a标签的字段
12 | list_display_links = ('id', 'show_content')
13 | search_fields = ('author__username', 'belong__title')
14 |
15 | # 使用方法来自定义一个字段,并且给这个字段设置一个名称
16 | def show_content(self, obj):
17 | return obj.content if len(obj.content) < 30 else f'{obj.content[:30]}...'
18 |
19 | show_content.short_description = '评论内容'
20 |
21 |
22 | @admin.register(Notification)
23 | class NotificationAdmin(admin.ModelAdmin):
24 | date_hierarchy = 'create_date'
25 | list_display = ('id', 'create_p', 'create_date', 'comment', 'is_read')
26 | list_filter = ('create_p', 'is_read',)
27 | search_fields = ('create_p__username', 'comment__content')
28 |
29 | # 允许直接编辑的字段,对于布尔值的字段,这个非常有用
30 | list_editable = ('is_read',)
31 |
32 |
33 | @admin.register(SystemNotification)
34 | class SystemNotificationAdmin(admin.ModelAdmin):
35 | date_hierarchy = 'create_date'
36 | list_display = ('title', 'get_users', 'create_date', 'show_content', 'is_read')
37 | list_filter = ('get_p', 'is_read',)
38 | search_fields = ('title',)
39 |
40 | # 允许直接编辑的字段,对于布尔值的字段,这个非常有用
41 | list_editable = ('is_read',)
42 |
43 | filter_horizontal = ('get_p',) # 给多选增加一个左右添加的框
44 |
45 | # 使用方法来自定义一个字段,并且给这个字段设置一个名称
46 | def show_content(self, obj):
47 | return obj.content if len(obj.content) < 30 else f'{obj.content[:30]}...'
48 |
49 | def get_users(self, obj):
50 | return ", ".join([user.username for user in obj.get_p.all()])
51 |
52 | get_users.short_description = '收信人'
53 |
54 | show_content.short_description = '推送内容'
55 |
--------------------------------------------------------------------------------
/apps/comment/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class CommentConfig(AppConfig):
5 | name = 'comment'
6 | verbose_name = '评论管理'
7 |
8 | def ready(self):
9 | from . import signals # 导入信号处理程序模块
10 |
--------------------------------------------------------------------------------
/apps/comment/migrations/0002_systemnotification.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-04 07:26
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 | import django.db.models.deletion
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12 | ('comment', '0001_initial'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='SystemNotification',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='推送时间')),
21 | ('is_read', models.BooleanField(default=False, verbose_name='是否已读')),
22 | ('title', models.CharField(max_length=50, verbose_name='标题')),
23 | ('content', models.TextField(help_text='支持html格式的内容', verbose_name='通知内容')),
24 | ('get_p', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='systemnotification_recipient', to=settings.AUTH_USER_MODEL, verbose_name='收信人')),
25 | ],
26 | options={
27 | 'verbose_name': '系统通知',
28 | 'verbose_name_plural': '系统通知',
29 | 'ordering': ['-create_date'],
30 | },
31 | ),
32 | ]
33 |
--------------------------------------------------------------------------------
/apps/comment/migrations/0003_auto_20230708_0641.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-08 06:41
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11 | ('comment', '0002_systemnotification'),
12 | ]
13 |
14 | operations = [
15 | migrations.RemoveField(
16 | model_name='systemnotification',
17 | name='get_p',
18 | ),
19 | migrations.AddField(
20 | model_name='systemnotification',
21 | name='get_p',
22 | field=models.ManyToManyField(related_name='systemnotification_recipient', to=settings.AUTH_USER_MODEL, verbose_name='收信人'),
23 | ),
24 | ]
25 |
--------------------------------------------------------------------------------
/apps/comment/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/comment/signals.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.dispatch import receiver
3 | from django.db.models.signals import post_save
4 | from .models import ArticleComment, Notification
5 |
6 |
7 | @receiver(post_save, sender=ArticleComment)
8 | def notify_handler(sender, instance, created, **kwargs):
9 | the_article = instance.belong
10 | create_p = instance.author
11 | # 判断是否是第一次生成评论,后续修改评论不会再次激活信号
12 | if created:
13 | if instance.rep_to:
14 | '''如果评论是一个回复评论,则同时通知给文章作者和回复的评论人,如果2者相等,则只通知一次'''
15 | if the_article.author == instance.rep_to.author:
16 | get_p = instance.rep_to.author
17 | if create_p != get_p:
18 | new_notify = Notification(create_p=create_p, get_p=get_p, comment=instance)
19 | new_notify.save()
20 | else:
21 | get_p1 = the_article.author
22 | if create_p != get_p1:
23 | new1 = Notification(create_p=create_p, get_p=get_p1, comment=instance)
24 | new1.save()
25 | get_p2 = instance.rep_to.author
26 | if create_p != get_p2:
27 | new2 = Notification(create_p=create_p, get_p=get_p2, comment=instance)
28 | new2.save()
29 | else:
30 | '''如果评论是一个一级评论而不是回复其他评论并且不是作者自评,则直接通知给文章作者'''
31 | get_p = the_article.author
32 | if create_p != get_p:
33 | new_notify = Notification(create_p=create_p, get_p=get_p, comment=instance)
34 | new_notify.save()
35 |
--------------------------------------------------------------------------------
/apps/comment/static/comment/css/base_comment.css:
--------------------------------------------------------------------------------
1 | #no-editor{background-color:#f5f5f5;border-radius:4px;}#emoji-btns,.editor-btns .btn{background:#fff;}#emoji-btns:hover,.editor-btns .btn:hover{background:#f4f4f4;}#emoji-btns:focus,.editor-btns .btn:focus{outline:0;box-shadow:none;}#emoji-btns:active,.editor-btns .btn:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.editor-btns img{width:24px;height:24px;}.CodeMirror,.CodeMirror-scroll{min-height:100px;}.editor-statusbar span{min-width:0;}.editor-toolbar,.CodeMirror{border-radius:0!important;}.editor-toolbar a{margin:0 .15em;}.hidden{display:none!important;}#comment-list img{display:block;max-width:100%;height:auto;margin-right:auto;margin-left:auto;}.comment-parent{border-top:1px solid #f0f0f0;}.comment-parent .avatar{width:40px;height:40px;margin-right:1rem;border-radius:50%;}.comment-child{border-top:1px dashed #f0f0f0;}.comment-child .avatar{width:35px;height:35px;margin-right:1rem;border-radius:50%;margin-top:5px;}#comment-list table{width:100%;max-width:100%;margin-bottom:1rem;background-color:transparent;}#comment-list table th,#comment-list table td{padding:2px 15px;border:1px solid #95a5a6;}#comment-list table th{background-color:#212529;color:#fff;}#comment-list p{margin-bottom:1em;}.rep-btn{color:#868e96;}.rep-btn:hover{color:#ea6f5a;}.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word){background:none;}#comment-list .comment-emoji-img{display:inline;height:1.1em;margin-right:2px;margin-left:2px;margin-bottom:2px;}@media (min-width:1200px){.comment-parent .avatar{margin-top:5px;}}
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/+1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/+1.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/angry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/angry.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/anguished.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/anguished.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/blush.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/blush.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/broken_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/broken_heart.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/clap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/clap.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/cold_sweat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/cold_sweat.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/confounded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/confounded.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/cry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/cry.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/disappointed_relieved.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/disappointed_relieved.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/dizzy_face.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/dizzy_face.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/dog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/dog.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/fearful.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/fearful.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/fist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/fist.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/flushed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/flushed.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/frowning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/frowning.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/grin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/grin.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/heart.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/heart_eyes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/heart_eyes.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/heartbeat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/heartbeat.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/hushed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/hushed.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/innocent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/innocent.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/joy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/joy.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/kissing_closed_eyes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/kissing_closed_eyes.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/kissing_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/kissing_heart.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/mask.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/no_mouth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/no_mouth.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/pensive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/pensive.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/persevere.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/persevere.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/pray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/pray.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/relieved.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/relieved.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/scream.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/scream.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/sleepy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/sleepy.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/smile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/smile.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/smiley.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/smiley.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/smirk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/smirk.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/sob.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/sob.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/sparkling_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/sparkling_heart.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/stuck_out_tongue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/stuck_out_tongue.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/stuck_out_tongue_closed_eyes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/stuck_out_tongue_closed_eyes.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/stuck_out_tongue_winking_eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/stuck_out_tongue_winking_eye.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/sunglasses.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/sunglasses.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/sweat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/sweat.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/sweat_smile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/sweat_smile.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/unamused.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/unamused.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/v.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/worried.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/worried.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/emoji/yum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/emoji/yum.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/js/notification.js:
--------------------------------------------------------------------------------
1 | $(function(){$(".to_read button,.to_delete button").click(function(){const id=$(this).data('id');const tag=$(this).data('tag');const CSRF=$(this).data('csrf');const URL=$(this).data('url');$.ajaxSetup({data:{'csrfmiddlewaretoken':CSRF}});$.ajax({type:'post',url:URL,data:{'id':id,'tag':tag},dataType:'json',success:function(ret){window.location.reload()},error:function(ret){alert(ret.msg)}})})});
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/aini_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/aini_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/baibai_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/baibai_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/baobao_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/baobao_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/beishang_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/beishang_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/bingbujiandan_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/bingbujiandan_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/bishi_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/bishi_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/bizui_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/bizui_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/chanzui_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/chanzui_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/chigua_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/chigua_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/chongjing_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/chongjing_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/dahaqian_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/dahaqian_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/dalian_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/dalian_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/ding_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/ding_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/doge02_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/doge02_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/erha_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/erha_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/gui_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/gui_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/guzhang_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/guzhang_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/haha_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/haha_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/heng_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/heng_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/huaixiao_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/huaixiao_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/huaxin_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/huaxin_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/jiyan_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/jiyan_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/kelian_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/kelian_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/ku_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/ku_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/kuxiao_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/kuxiao_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/leimu_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/leimu_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/miaomiao_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/miaomiao_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/ningwen_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/ningwen_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/nu_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/nu_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/qian_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/qian_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/sikao_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/sikao_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/taikaixin_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/taikaixin_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/tanshou_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/tanshou_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/tianping_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/tianping_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/touxiao_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/touxiao_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/tu_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/tu_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/wabi_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/wabi_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/weiqu_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/weiqu_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/wenhao_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/wenhao_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/wosuanle_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/wosuanle_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/wu_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/wu_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/xiaoerbuyu_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/xiaoerbuyu_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/xiaoku_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/xiaoku_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/xixi_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/xixi_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/yinxian_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/yinxian_org.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/yun_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/yun_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/zhouma_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/zhouma_thumb.png
--------------------------------------------------------------------------------
/apps/comment/static/comment/weibo/zhuakuang_org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/comment/static/comment/weibo/zhuakuang_org.png
--------------------------------------------------------------------------------
/apps/comment/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
/apps/comment/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/comment/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.urls import path
3 | from .views import AddCommentView, NotificationView, mark_to_read, mark_to_delete
4 |
5 | urlpatterns = [
6 | path('add/', AddCommentView, name='add_comment'),
7 | path('notification/', NotificationView, name='notification'),
8 | path('notification/no-read/', NotificationView, {'is_read': 'false'}, name='notification_no_read'),
9 | path('notification/mark-to-read/', mark_to_read, name='mark_to_read'),
10 | path('notification/mark-to-delete/', mark_to_delete, name='mark_to_delete'),
11 | ]
12 |
--------------------------------------------------------------------------------
/apps/easytask/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/easytask/__init__.py
--------------------------------------------------------------------------------
/apps/easytask/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/apps/easytask/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class EasytaskConfig(AppConfig):
5 | name = 'easytask'
6 |
--------------------------------------------------------------------------------
/apps/easytask/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/easytask/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/easytask/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/apps/easytask/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/easytask/utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import time
3 |
4 |
5 | class TaskResponse(object):
6 | def __init__(self, code=0, data=None, message="", error=""):
7 | self.code = code
8 | self.data = data or {}
9 | self.message = message
10 | self.error = error
11 | self.start_time = time.time()
12 |
13 | def __getitem__(self, key):
14 | return getattr(self, key)
15 |
16 | def __setitem__(self, key, value):
17 | setattr(self, key, value)
18 |
19 | def as_dict(self):
20 | data = {
21 | 'code': self.code,
22 | 'data': self.data,
23 | 'message': self.message,
24 | 'error': self.error,
25 | 'time': round(time.time() - self.start_time, 3)
26 | }
27 | return data
28 |
29 |
30 | class ErrorTaskResponse(TaskResponse):
31 | def __init__(self, code=1, data=None, message="", error=""):
32 | super(ErrorTaskResponse, self).__init__(code, data, message, error)
33 |
34 |
35 | if __name__ == '__main__':
36 | response = TaskResponse()
37 | response.data = {'result': "xx"}
38 | print(response)
39 |
--------------------------------------------------------------------------------
/apps/easytask/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 |
--------------------------------------------------------------------------------
/apps/monitor/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'monitor.apps.MonitorConfig'
2 |
--------------------------------------------------------------------------------
/apps/monitor/actions.py:
--------------------------------------------------------------------------------
1 | import json
2 | from datetime import datetime
3 |
4 |
5 | def action_check_host_status(recipient_list=None, times=None, ignore_hours=None):
6 | from django.conf import settings
7 | from django.core.mail import send_mail
8 | from .models import MonitorServer
9 |
10 | current_date = datetime.now()
11 |
12 | # 忽略的检查时段,这些时段不检查状态
13 | # 这个忽略的意义是因为运营商会定期断网更新IP,导致上报失败触发告警,比如电信是4点多断网一段时间
14 | ignore_hours = ignore_hours or []
15 |
16 | if current_date.hour in ignore_hours:
17 | return f'Ignore period for {ignore_hours}, do not check.'
18 |
19 | # 可以通过参数传递通知的频率
20 | times = times or [1, 10, 60, 60 * 4, 60 * 24]
21 |
22 | if not recipient_list:
23 | return 'No recipient_list, please set it.'
24 |
25 | if hasattr(settings, 'DEFAULT_FROM_EMAIL') and settings.DEFAULT_FROM_EMAIL:
26 | from_email = settings.DEFAULT_FROM_EMAIL
27 | else:
28 | # 如果未设置发件人邮箱,设置为空,直接退出
29 | return 'Email configuration not set.'
30 |
31 | alarm_list = []
32 | hosts = MonitorServer.objects.filter(
33 | secret_key__isnull=False,
34 | secret_value__isnull=False,
35 | data__isnull=False,
36 | active=True,
37 | alarm=True
38 | )
39 | for host in hosts:
40 | # 转换成分钟
41 | m = int((current_date - host.update_date).total_seconds() / 60)
42 | # 多个时间点发送
43 | if m in times:
44 | msg = f'警告:节点 {host.name} 离线 {m} 分钟'
45 | alarm_list.append(msg)
46 | else:
47 | continue
48 | if all([alarm_list, from_email, recipient_list]):
49 | subject = f'⚠️服务监控告警 {current_date.strftime("%Y-%m-%d %H:%M:%S")}'
50 | message = '\n'.join(alarm_list)
51 | ok_num = send_mail(subject, message, from_email, recipient_list)
52 | return f"Send email ok: {ok_num}"
53 |
54 | return "Not alarm !!!"
55 |
--------------------------------------------------------------------------------
/apps/monitor/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import MonitorServer
3 |
4 |
5 | # Register your models here.
6 | @admin.register(MonitorServer)
7 | class MonitorServerViewAdmin(admin.ModelAdmin):
8 | list_display = ('name', 'interval', 'sort_order', 'active', 'alarm', 'username', 'secret_key')
9 | ordering = ('sort_order',)
10 | list_editable = ('sort_order', 'active', 'alarm')
11 |
12 | readonly_fields = ('secret_key', 'secret_value', 'data')
13 |
--------------------------------------------------------------------------------
/apps/monitor/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class MonitorConfig(AppConfig):
5 | name = 'monitor'
6 | verbose_name = '监控管理'
7 |
--------------------------------------------------------------------------------
/apps/monitor/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-03-31 20:01
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | initial = True
9 |
10 | dependencies = [
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='MonitorServer',
16 | fields=[
17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18 | ('name', models.CharField(help_text='用于看板中显示', max_length=30, unique=True, verbose_name='名称')),
19 | ('interval', models.IntegerField(default=5, help_text='上报间隔时间,超过这个时间的两倍还没有更新数据就标记为离线状态,单位:秒', verbose_name='上报间隔')),
20 | ('sort_order', models.IntegerField(default=99, help_text='自定义排序依据', verbose_name='排序')),
21 | ('push_url', models.CharField(help_text='客户端推送的地址,为了支持代理推送或者本地推送', max_length=60, verbose_name='推送地址')),
22 | ('username', models.CharField(help_text='推送用户名,唯一', max_length=10, unique=True, verbose_name='用户名')),
23 | ('password', models.CharField(help_text='第一次添加后自动生成密钥,更改后会重新生成密钥', max_length=10, unique=True, verbose_name='密码')),
24 | ('secret_key', models.CharField(blank=True, help_text='保存后自动生成', max_length=64, null=True, verbose_name='加密Key')),
25 | ('secret_value', models.CharField(blank=True, help_text='保存后自动生成', max_length=256, null=True, verbose_name='密钥')),
26 | ('data', models.TextField(blank=True, help_text='json格式', null=True, verbose_name='上报数据')),
27 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
28 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
29 | ],
30 | options={
31 | 'verbose_name': '监控服务',
32 | 'verbose_name_plural': '监控服务',
33 | 'ordering': ['sort_order'],
34 | },
35 | ),
36 | ]
37 |
--------------------------------------------------------------------------------
/apps/monitor/migrations/0002_monitorserver_active.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-04-04 23:59
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('monitor', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='monitorserver',
15 | name='active',
16 | field=models.BooleanField(default=True, help_text='用来过滤,无效的不显示', verbose_name='是否有效'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/monitor/migrations/0003_monitorserver_alarm.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-04-28 14:54
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('monitor', '0002_monitorserver_active'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='monitorserver',
15 | name='alarm',
16 | field=models.BooleanField(default=False, help_text='默认不告警', verbose_name='是否告警'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/apps/monitor/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/monitor/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/monitor/static/monitor/img/mac-os.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/monitor/static/monitor/img/windows.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/monitor/templates/monitor/demo.html:
--------------------------------------------------------------------------------
1 | {% extends 'monitor/base.html' %}
2 | {% block demo %}
3 |
4 |
5 | 此页面数据为监控面板演示数据,只用来演示监控效果。真实数据需要服务器上报,且管理页面只有管理员有权限查看。
6 |
7 |
10 |
11 | {% endblock %}
12 |
13 | {% block script %}
14 |
20 | {% endblock %}
--------------------------------------------------------------------------------
/apps/monitor/templates/monitor/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'monitor/base.html' %}
2 | {% block script %}
3 |
9 | {% endblock %}
--------------------------------------------------------------------------------
/apps/monitor/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/monitor/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from .views import (index,
3 | demo,
4 | get_server_list,
5 | get_server_list_for_demo,
6 | server_push)
7 |
8 | urlpatterns = [
9 | path('', index, name='index'),
10 | path('demo', demo, name='demo'),
11 | path('servers', get_server_list, name='get_server_list'),
12 | path('servers/demo', get_server_list_for_demo, name='get_server_list_for_demo'),
13 | path('server/push', server_push, name='server_push'),
14 | ]
15 |
--------------------------------------------------------------------------------
/apps/oauth/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'oauth.apps.OauthConfig'
--------------------------------------------------------------------------------
/apps/oauth/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Ouser
3 |
4 |
5 | @admin.register(Ouser)
6 | class OuserAdmin(admin.ModelAdmin):
7 | list_display = ('username', 'email', 'is_staff', 'is_active', 'date_joined')
8 | fieldsets = (
9 | ('基础信息', {'fields': (('username', 'email'), ('link',), ('avatar',))}),
10 | ('权限信息', {'fields': (('is_active', 'is_staff', 'is_superuser'),
11 | 'groups', 'user_permissions')}),
12 | ('重要日期', {'fields': (('last_login', 'date_joined'),)}),
13 | )
14 | filter_horizontal = ('groups', 'user_permissions',)
15 | list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
16 | search_fields = ('username', 'email')
17 |
--------------------------------------------------------------------------------
/apps/oauth/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class OauthConfig(AppConfig):
5 | name = 'oauth'
6 | verbose_name = '用户管理'
7 |
8 | def ready(self):
9 | from . import signals # 导入信号处理程序模块
10 |
--------------------------------------------------------------------------------
/apps/oauth/forms.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django import forms
3 | from .models import Ouser
4 |
5 | class ProfileForm(forms.ModelForm):
6 | class Meta:
7 | model = Ouser
8 | fields = ['link','avatar']
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/oauth/migrations/0002_auto_20230423_1145.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.27 on 2023-04-23 11:45
2 |
3 | from django.db import migrations
4 | import imagekit.models.fields
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('oauth', '0001_initial'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='ouser',
16 | name='avatar',
17 | field=imagekit.models.fields.ProcessedImageField(default='avatar/default.png', upload_to='avatar/%Y/%m/%d/%H-%M-%S', verbose_name='头像'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/apps/oauth/migrations/0003_auto_20230709_1237.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2023-07-09 12:37
2 |
3 | from django.db import migrations
4 | import imagekit.models.fields
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('oauth', '0002_auto_20230423_1145'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='ouser',
16 | name='avatar',
17 | field=imagekit.models.fields.ProcessedImageField(default='avatar/default/default.png', upload_to='avatar/upload/%Y/%m/%d/%H-%M-%S', verbose_name='头像'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/apps/oauth/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/oauth/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/oauth/models.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from django.db import models
4 | from django.contrib.auth.models import AbstractUser
5 | from imagekit.models import ProcessedImageField
6 | from imagekit.processors import ResizeToFill
7 |
8 | from django.conf import settings
9 |
10 |
11 | class Ouser(AbstractUser):
12 | link = models.URLField('个人网址', blank=True, help_text='提示:网址必须填写以http开头的完整形式')
13 | avatar = ProcessedImageField(upload_to='avatar/upload/%Y/%m/%d/%H-%M-%S',
14 | default='avatar/default/default.png',
15 | verbose_name='头像',
16 | processors=[ResizeToFill(80, 80)]
17 | )
18 |
19 | class Meta:
20 | verbose_name = '用户'
21 | verbose_name_plural = verbose_name
22 | ordering = ['-id']
23 |
24 | def __str__(self):
25 | return self.username
26 |
--------------------------------------------------------------------------------
/apps/oauth/signals.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import random
3 | from django.db.models.signals import pre_save
4 | from django.dispatch import receiver
5 | from .models import Ouser
6 |
7 |
8 | @receiver(pre_save, sender=Ouser)
9 | def generate_avatar(sender, instance, **kwargs):
10 | if instance._state.adding:
11 | # 随机选择一个头像地址
12 | random_avatar = 'avatar/default/default{}.png'.format(random.randint(1, 10))
13 | instance.avatar = random_avatar
14 |
--------------------------------------------------------------------------------
/apps/oauth/templates/oauth/change_profile.html:
--------------------------------------------------------------------------------
1 | {% extends 'blog/base.html' %}
2 | {% load crispy_forms_tags %}
3 | {% load static %}
4 |
5 | {% block metas %}
6 |
7 |
8 | {% endblock %}
9 |
10 | {% block top-file %}
11 |
12 | {% endblock %}
13 |
14 | {% block head_title%}个人信息修改{% endblock%}
15 |
16 | {% block base_content %}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 |
37 |
38 |
39 |
40 |
41 | {% endblock %}
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/apps/oauth/templates/oauth/tags/user_avatar.html:
--------------------------------------------------------------------------------
1 | {% load oauth_tags %}
2 | {% if user.socialaccount_set.exists and user.avatar.url == '/media/avatar/default.png' %}
3 | {% if ".sinaimg.cn" in user.socialaccount_set.all.0.get_avatar_url %}
4 |
5 | {% else %}
6 |
7 | {% endif %}
8 | {% else %}
9 |
10 | {% endif %}
--------------------------------------------------------------------------------
/apps/oauth/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
/apps/oauth/templatetags/oauth_tags.py:
--------------------------------------------------------------------------------
1 | # 创建了新的tags标签文件后必须重启服务器
2 |
3 | from django import template
4 |
5 | register = template.Library()
6 |
7 |
8 | @register.inclusion_tag('oauth/tags/user_avatar.html')
9 | def get_user_avatar_tag(user):
10 | '''返回用户的头像,是一个img标签'''
11 | return {'user': user}
12 |
13 |
14 | @register.simple_tag
15 | def http_to_https(link):
16 | '''将http链接替换成https,目的是将微博的头像图床地址换成HTTPS'''
17 | return link.replace('http://', 'https://')
18 |
19 |
20 | @register.simple_tag
21 | def get_user_link(user):
22 | '''
23 | 获取认证用户的link,并判断用户是哪种认证方式(Github,Weibo,邮箱)
24 | 参考 get_social_accounts(user) 的用法
25 | :param user: 一个USER对象
26 | :return: 返回用户的link和注册方式以及是否验证过邮箱地址,link的优先顺序是user.link,其次是github主页,
27 | 考虑到很多人不愿意展示微博主页,所以不展示weibo主页
28 | '''
29 | info = {
30 | 'link': None,
31 | 'provider': None,
32 | 'is_verified': False
33 | }
34 | accounts = {}
35 | for account in user.socialaccount_set.all().iterator():
36 | providers = accounts.setdefault(account.provider, [])
37 | providers.append(account)
38 | if accounts:
39 | for key in ['github', 'weibo']:
40 | account_users = accounts.get(key)
41 | if account_users:
42 | account_user = account_users[0]
43 | the_link = account_user.get_profile_url()
44 | the_provider = account_user.get_provider().name
45 | if key == 'github':
46 | info['link'] = the_link
47 | if user.link:
48 | info['link'] = user.link
49 | info['provider'] = the_provider
50 | info['is_verified'] = True
51 | else:
52 | the_link = user.link
53 | if the_link:
54 | info['link'] = the_link
55 | for emailaddress in user.emailaddress_set.all().iterator():
56 | if emailaddress.verified:
57 | info['is_verified'] = True
58 | return info
59 |
--------------------------------------------------------------------------------
/apps/oauth/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/oauth/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.urls import path
3 | from .views import profile_view, change_profile_view
4 |
5 |
6 | urlpatterns = [
7 | path('profile/',profile_view,name='profile'),
8 | path('profile/change/',change_profile_view,name='change_profile'),
9 |
10 | ]
--------------------------------------------------------------------------------
/apps/oauth/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect
2 | from django.contrib.auth.decorators import login_required
3 |
4 | from .forms import ProfileForm
5 | from django.contrib import messages
6 | import os
7 |
8 |
9 | # Create your views here.
10 |
11 | @login_required
12 | def profile_view(request):
13 | return render(request, 'oauth/profile.html')
14 |
15 |
16 | @login_required
17 | def change_profile_view(request):
18 | if request.method == 'POST':
19 | old_avatar_file = request.user.avatar.path
20 | old_avatar_url = request.user.avatar.url
21 | # 上传文件需要使用request.FILES
22 | form = ProfileForm(request.POST, request.FILES, instance=request.user)
23 | if form.is_valid():
24 | if not old_avatar_url == '/media/avatar/default.png':
25 | if os.path.exists(old_avatar_file):
26 | os.remove(old_avatar_file)
27 | form.save()
28 | # 添加一条信息,表单验证成功就重定向到个人信息页面
29 | messages.add_message(request, messages.SUCCESS, '个人信息更新成功!')
30 | return redirect('oauth:profile')
31 | else:
32 | # 不是POST请求就返回空表单
33 | form = ProfileForm(instance=request.user)
34 | return render(request, 'oauth/change_profile.html', context={'form': form})
35 |
--------------------------------------------------------------------------------
/apps/portinfo/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'portinfo.apps.PortinfoConfig'
2 |
--------------------------------------------------------------------------------
/apps/portinfo/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Port
3 |
4 |
5 | @admin.register(Port)
6 | class PortAdmin(admin.ModelAdmin):
7 | list_display = ['port_number', 'protocol', 'service_name', 'description']
8 | list_filter = ('protocol',)
9 | search_fields = ['port_number', 'protocol', 'service_name']
10 |
--------------------------------------------------------------------------------
/apps/portinfo/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class PortinfoConfig(AppConfig):
5 | name = 'portinfo'
6 | verbose_name = '端口信息'
7 |
--------------------------------------------------------------------------------
/apps/portinfo/management/commands/load_initial_data.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | from django.core.management.base import BaseCommand
4 | from portinfo.models import Port
5 |
6 |
7 | class Command(BaseCommand):
8 | help = 'Load initial port data from ports.json'
9 |
10 | def handle(self, *args, **options):
11 | with open(os.path.join(os.path.dirname(__file__), 'ports.json'), 'r',
12 | encoding='utf-8') as file:
13 | port_data = json.load(file)
14 |
15 | for entry in port_data:
16 | port_number = entry.get('port_number')
17 | protocol = entry.get('protocol')
18 | service_name = entry.get('service_name')
19 | description = entry.get('description')
20 | default_status = entry.get('default_status')
21 | common_usage = entry.get('common_usage')
22 | notes = entry.get('notes')
23 |
24 | port, created = Port.objects.update_or_create(
25 | port_number=port_number,
26 | protocol=protocol,
27 | service_name=service_name,
28 | defaults={
29 | 'description': description,
30 | 'default_status': default_status,
31 | 'common_usage': common_usage,
32 | 'notes': notes
33 | }
34 | )
35 |
36 | if created:
37 | self.stdout.write(
38 | self.style.SUCCESS(f'Successfully created port {port_number}/{protocol}'))
39 | else:
40 | self.stdout.write(
41 | self.style.SUCCESS(f'Successfully updated port {port_number}/{protocol}'))
42 |
43 | self.stdout.write(self.style.SUCCESS('Successfully loaded port data'))
44 |
--------------------------------------------------------------------------------
/apps/portinfo/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-06-15 14:07
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | initial = True
9 |
10 | dependencies = [
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='Port',
16 | fields=[
17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18 | ('port_number', models.IntegerField()),
19 | ('protocol', models.CharField(max_length=10)),
20 | ('service_name', models.CharField(max_length=100)),
21 | ('description', models.TextField()),
22 | ('default_status', models.CharField(max_length=20)),
23 | ('common_usage', models.CharField(max_length=200)),
24 | ('notes', models.TextField(blank=True, null=True)),
25 | ],
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/apps/portinfo/migrations/0002_auto_20240615_1412.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.28 on 2024-06-15 14:12
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('portinfo', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterModelOptions(
14 | name='port',
15 | options={'ordering': ['port_number'], 'verbose_name': '端口', 'verbose_name_plural': '端口'},
16 | ),
17 | migrations.AlterField(
18 | model_name='port',
19 | name='common_usage',
20 | field=models.CharField(max_length=200, verbose_name='使用场景'),
21 | ),
22 | migrations.AlterField(
23 | model_name='port',
24 | name='default_status',
25 | field=models.CharField(max_length=20, verbose_name='默认状态'),
26 | ),
27 | migrations.AlterField(
28 | model_name='port',
29 | name='description',
30 | field=models.TextField(verbose_name='描述'),
31 | ),
32 | migrations.AlterField(
33 | model_name='port',
34 | name='notes',
35 | field=models.TextField(blank=True, null=True, verbose_name='备注'),
36 | ),
37 | migrations.AlterField(
38 | model_name='port',
39 | name='port_number',
40 | field=models.IntegerField(verbose_name='端口号'),
41 | ),
42 | migrations.AlterField(
43 | model_name='port',
44 | name='protocol',
45 | field=models.CharField(help_text='一般填写 TCP,UDP,TCP/UDP 等', max_length=10, verbose_name='协议'),
46 | ),
47 | migrations.AlterField(
48 | model_name='port',
49 | name='service_name',
50 | field=models.CharField(max_length=100, verbose_name='服务名称'),
51 | ),
52 | ]
53 |
--------------------------------------------------------------------------------
/apps/portinfo/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/portinfo/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/portinfo/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | class Port(models.Model):
5 | port_number = models.IntegerField('端口号')
6 | protocol = models.CharField('协议', max_length=10, help_text='一般填写 TCP,UDP,TCP/UDP 等')
7 | service_name = models.CharField('服务名称', max_length=100)
8 | description = models.TextField('描述')
9 | default_status = models.CharField('默认状态', max_length=20)
10 | common_usage = models.CharField('使用场景', max_length=200)
11 | notes = models.TextField('备注', null=True, blank=True)
12 |
13 | class Meta:
14 | verbose_name = '端口'
15 | verbose_name_plural = verbose_name
16 | ordering = ['port_number']
17 |
18 | def __str__(self):
19 | return f"{self.port_number}/{self.protocol} - {self.service_name}"
20 |
--------------------------------------------------------------------------------
/apps/portinfo/static/portinfo/js/dataTables.bootstrap4.min.js:
--------------------------------------------------------------------------------
1 | /*! DataTables Bootstrap 4 integration
2 | * © SpryMedia Ltd - datatables.net/license
3 | */
4 | !function(n){var o,r;"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(e){return n(e,window,document)}):"object"==typeof exports?(o=require("jquery"),r=function(e,t){t.fn.dataTable||require("datatables.net")(e,t)},"undefined"==typeof window?module.exports=function(e,t){return e=e||window,t=t||o(e),r(e,t),n(t,0,e.document)}:(r(window,o),module.exports=n(o,window,window.document))):n(jQuery,window,document)}(function(d,e,t){"use strict";var n=d.fn.dataTable;return d.extend(!0,n.defaults,{renderer:"bootstrap"}),d.extend(!0,n.ext.classes,{container:"dt-container dt-bootstrap4",search:{input:"form-control form-control-sm"},length:{select:"custom-select custom-select-sm form-control form-control-sm"},processing:{container:"dt-processing card"}}),n.ext.renderer.pagingButton.bootstrap=function(e,t,n,o,r){var a=["dt-paging-button","page-item"],o=(o&&a.push("active"),r&&a.push("disabled"),d("").addClass(a.join(" ")));return{display:o,clicker:d("",{href:r?null:"#",class:"page-link"}).html(n).appendTo(o)}},n.ext.renderer.pagingContainer.bootstrap=function(e,t){return d("").addClass("pagination").append(t)},n.ext.renderer.layout.bootstrap=function(e,t,n){var o=d("
",{class:n.full?"row justify-content-md-center":"row justify-content-between"}).appendTo(t);d.each(n,function(e,t){e=t.table?"col-12":"start"===e?"col-md-auto mr-auto":"end"===e?"col-md-auto ml-auto":"col-md";d("
",{id:t.id||null,class:e+" "+(t.className||"")}).append(t.contents).appendTo(o)})},n});
--------------------------------------------------------------------------------
/apps/portinfo/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/portinfo/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from .views import PortView
3 |
4 | urlpatterns = [
5 | path('', PortView.as_view(), name='index'),
6 | ]
7 |
--------------------------------------------------------------------------------
/apps/portinfo/views.py:
--------------------------------------------------------------------------------
1 | from django.views import generic
2 |
3 | from .models import Port
4 |
5 |
6 | class PortView(generic.ListView):
7 | model = Port
8 | template_name = 'portinfo/index.html'
9 | context_object_name = 'ports'
10 | paginate_by = 2000
11 |
--------------------------------------------------------------------------------
/apps/resume/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'resume.apps.ResumeConfig'
2 |
--------------------------------------------------------------------------------
/apps/resume/admin.py:
--------------------------------------------------------------------------------
1 | from django.apps import apps
2 | from django.conf import settings
3 | from django.contrib import admin
4 |
5 | from .models import Resume, ResumeTemplate
6 |
7 |
8 | # Register your models here.
9 |
10 | @admin.register(ResumeTemplate)
11 | class ResumeTemplateAdmin(admin.ModelAdmin):
12 | # 在查看修改的时候显示的属性,第一个字段带有 标签,所以最好放标题
13 | list_display = ('id', 'name', 'description')
14 |
15 | # 设置需要添加 标签的字段
16 | list_display_links = ('name',)
17 |
18 | # 限制用户权限,只能超管可以编辑
19 | def get_queryset(self, request):
20 | qs = super(ResumeTemplateAdmin, self).get_queryset(request)
21 | if request.user.is_superuser:
22 | return qs
23 | return None
24 |
25 |
26 | @admin.register(Resume)
27 | class ResumeAdmin(admin.ModelAdmin):
28 | # 这个的作用是给出一个筛选机制,一般按照时间比较好
29 | date_hierarchy = 'create_date'
30 |
31 | # 在查看修改的时候显示的属性,第一个字段带有 标签,所以最好放标题
32 | list_display = ('id', 'title', 'author', 'is_open', 'slug', 'create_date', 'update_date')
33 |
34 | # 设置需要添加 标签的字段
35 | list_display_links = ('title',)
36 |
37 | # 激活过滤器,这个很有用
38 | list_filter = ('create_date', 'is_open')
39 |
40 | # 限制用户权限,只能看到自己编辑的简历
41 | def get_queryset(self, request):
42 | qs = super(ResumeAdmin, self).get_queryset(request)
43 | if request.user.is_superuser:
44 | return qs
45 | return qs.filter(author=request.user)
46 |
47 | def formfield_for_foreignkey(self, db_field, request, **kwargs):
48 | User = apps.get_model(settings.AUTH_USER_MODEL)
49 | if db_field.name == 'author':
50 | if request.user.is_superuser:
51 | kwargs['queryset'] = User.objects.filter(is_staff=True, is_active=True)
52 | else:
53 | kwargs['queryset'] = User.objects.filter(id=request.user.id)
54 | return super(ResumeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
55 |
--------------------------------------------------------------------------------
/apps/resume/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ResumeConfig(AppConfig):
5 | name = 'resume'
6 | verbose_name = '简历管理'
7 |
--------------------------------------------------------------------------------
/apps/resume/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/resume/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/resume/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.conf import settings
3 | from django.shortcuts import reverse
4 |
5 |
6 | # Create your models here.
7 |
8 | class ResumeTemplate(models.Model):
9 | name = models.CharField('模板名称', max_length=20)
10 | description = models.TextField('描述', max_length=240)
11 | content = models.TextField('css内容')
12 |
13 | class Meta:
14 | verbose_name = '简历模板'
15 | verbose_name_plural = verbose_name
16 | ordering = ['name']
17 |
18 | def __str__(self):
19 | return self.name
20 |
21 |
22 | # 个人简历
23 | class Resume(models.Model):
24 | author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者',
25 | on_delete=models.PROTECT)
26 | title = models.CharField(max_length=150, verbose_name='简历标题')
27 | body = models.TextField(verbose_name='简历内容')
28 | create_date = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
29 | update_date = models.DateTimeField(verbose_name='修改时间', auto_now=True)
30 | slug = models.SlugField('访问地址', unique=True)
31 | is_open = models.BooleanField('是否公开', default=False)
32 |
33 | template = models.ForeignKey(ResumeTemplate, verbose_name='简历模板', on_delete=models.PROTECT)
34 |
35 | class Meta:
36 | verbose_name = '个人简历'
37 | verbose_name_plural = verbose_name
38 | ordering = ['-create_date']
39 |
40 | def __str__(self):
41 | if len(self.title) > 20:
42 | return self.title[:20] + '...'
43 | return self.title
44 |
45 | def get_absolute_url(self):
46 | return reverse('resume:detail', kwargs={'slug': self.slug})
47 |
--------------------------------------------------------------------------------
/apps/resume/static/resume/css/detail.css:
--------------------------------------------------------------------------------
1 | .flex-container {
2 | display: flex;
3 | }
4 |
5 | .flex-container .left {
6 | flex: auto;
7 | text-align: left;
8 | }
--------------------------------------------------------------------------------
/apps/resume/templates/resume/base.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {% block head_title %}{% endblock %}
11 | {% block metas %}
12 | {% endblock %}
13 |
15 |
16 |
17 |
18 |
19 | {% block top-file %}{% endblock %}
20 |
21 |
22 |
23 | {% block base_content %}{% endblock %}
24 |
25 |
26 |
27 |
28 | {% block end_file %}{% endblock %}
29 |
30 |
--------------------------------------------------------------------------------
/apps/resume/templates/resume/detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'resume/base.html' %}
2 | {% load static %}
3 |
4 | {% block head_title %}个人简历{% endblock %}
5 |
6 | {% block top-file %}
7 |
8 |
9 |
10 |
19 | {% endblock %}
20 |
21 | {% block base_content %}
22 |
23 |
24 |
25 |
{{ resume.body|safe }}
26 |
27 |
28 |
29 | {% endblock %}
30 |
31 | {% block end_file %}
32 |
50 | {% endblock %}
--------------------------------------------------------------------------------
/apps/resume/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 | import markdown
3 |
4 | from .utils import FlexExtension, BoxExtension, IconExtension
5 |
6 | # Create your tests here.
7 |
8 | text = """
9 | A regular paragraph of text.
10 |
11 | ::::
12 |
13 | :::left
14 | icon:info 男/1995.12
15 |
16 | icon:weixin qiufengblue
17 | :::
18 |
19 | ::: right
20 | icon:info 男/1995.12
21 |
22 | icon:weixin qiufengblue
23 | :::
24 |
25 | ::::
26 |
27 | Another regular paragraph of text.
28 |
29 | """
30 |
31 |
32 | class MarkdownTests(TestCase):
33 | def test_flex_extension(self):
34 | md = markdown.Markdown(extensions=[
35 | FlexExtension(),
36 | ])
37 | print(md.convert(text))
38 |
39 | def test_box_extension(self):
40 | md = markdown.Markdown(extensions=[
41 | BoxExtension(),
42 | ])
43 | html = md.convert(text)
44 | print(html)
45 |
46 | def test_icon_extension(self):
47 | md = markdown.Markdown(extensions=[
48 | IconExtension(),
49 | ])
50 | html = md.convert(text)
51 | print(html)
52 |
--------------------------------------------------------------------------------
/apps/resume/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.urls import path
3 |
4 | from .views import ResumeDetailView
5 |
6 | urlpatterns = [
7 | path('/', ResumeDetailView.as_view(), name='detail')
8 | ]
9 |
--------------------------------------------------------------------------------
/apps/resume/views.py:
--------------------------------------------------------------------------------
1 | from django.core.exceptions import PermissionDenied
2 | from django.views import generic
3 | from django.core.cache import cache
4 | from django.conf import settings
5 |
6 | import markdown
7 |
8 | from .models import Resume
9 | from .utils import FlexExtension, BoxExtension, IconExtension
10 |
11 |
12 | # Create your views here.
13 | class ResumeDetailView(generic.DetailView):
14 | model = Resume
15 | template_name = 'resume/detail.html'
16 | context_object_name = 'resume'
17 |
18 | def get_object(self, queryset=None):
19 | obj = super(ResumeDetailView, self).get_object()
20 | # 获取文章更新的时间,判断是否从缓存中取markdown,可以避免每次都转换
21 | ud = obj.update_date.strftime("%Y%m%d%H%M%S")
22 | md_key = self.context_object_name + ':markdown:{}:{}'.format(obj.id, ud)
23 | cache_md = cache.get(md_key)
24 | if cache_md and settings.DEBUG is False:
25 | obj.body = cache_md
26 | else:
27 | md = markdown.Markdown(extensions=[
28 | 'markdown.extensions.extra',
29 | 'markdown.extensions.codehilite',
30 | FlexExtension(),
31 | BoxExtension(),
32 | IconExtension()
33 | ])
34 | obj.body = md.convert(obj.body)
35 | cache.set(md_key, obj.body, 3600 * 24 * 30)
36 | return obj
37 |
38 | def dispatch(self, request, *args, **kwargs):
39 | """
40 | 检查当前登录的用户是否与模型实例中的用户匹配。如果匹配,说明当前用户是该模型实例的所有者,可以访问页面。
41 | 否则,抛出一个PermissionDenied异常,返回403 Forbidden错误。
42 | """
43 | obj = self.get_object()
44 | # 当简历不公开的时候,非所有者访问直接拒绝,公开的就不需要校验直接返回
45 | if obj.is_open is False and obj.author != request.user:
46 | raise PermissionDenied
47 | return super().dispatch(request, *args, **kwargs)
48 |
--------------------------------------------------------------------------------
/apps/rsshub/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'rsshub.apps.RsshubConfig'
2 |
--------------------------------------------------------------------------------
/apps/rsshub/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/apps/rsshub/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class RsshubConfig(AppConfig):
5 | name = 'rsshub'
6 | verbose_name = 'RSS管理'
7 |
--------------------------------------------------------------------------------
/apps/rsshub/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/rsshub/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/rsshub/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/apps/rsshub/templates/rsshub/rss.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {% if description %} {% endif %}
8 | {% for item in items %}
9 | -
10 |
11 |
12 | {% if item.description %}
13 |
14 | {% endif %}
15 |
16 | {% endfor %}
17 |
18 |
19 |
--------------------------------------------------------------------------------
/apps/rsshub/templatetags/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/rsshub/templatetags/__init__.py
--------------------------------------------------------------------------------
/apps/rsshub/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/rsshub/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.urls import path
3 | from .views import (juejin_hot_articles,
4 | cnblogs_pick,
5 | github_issues_ryf)
6 |
7 | urlpatterns = [
8 | path('juejin//', juejin_hot_articles, name='juejin_hot_articles'),
9 | path('cnblogs/pick', cnblogs_pick, name='cnblogs_pick'),
10 | path('ruanyf/weekly/issues', github_issues_ryf, name='github_issues_ryf'),
11 | ]
12 |
--------------------------------------------------------------------------------
/apps/tool/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'tool.apps.ToolConfig'
--------------------------------------------------------------------------------
/apps/tool/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import ToolCategory, ToolLink
3 | from django.conf import settings
4 |
5 | # Register your models here.
6 | if settings.TOOL_FLAG:
7 | @admin.register(ToolLink)
8 | class ToolLinkAdmin(admin.ModelAdmin):
9 | list_display = ('name', 'description', 'link', 'order_num', 'category')
10 |
11 | list_filter = ('category',)
12 |
13 | search_fields = ('name', 'link')
14 |
15 |
16 | @admin.register(ToolCategory)
17 | class ToolCategoryAdmin(admin.ModelAdmin):
18 | list_display = ('name', 'order_num', 'icon')
19 |
20 | search_fields = ('name',)
21 |
--------------------------------------------------------------------------------
/apps/tool/apis/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
/apps/tool/apis/bd_push.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import re
3 |
4 |
5 | def push_urls(url, urls):
6 | '''根据百度站长提供的API推送链接'''
7 | headers = {
8 | 'User-Agent': 'curl/7.12.1',
9 | 'Host': 'data.zz.baidu.com',
10 | 'Content-Type': 'text/plain',
11 | 'Content-Length': '83'
12 | }
13 | try:
14 | html = requests.post(url, headers=headers, data=urls, timeout=5).text
15 | return html
16 | except:
17 | return "{'error':404,'message':'请求超时,接口地址错误!'}"
18 |
19 |
20 | def get_urls(url):
21 | '''提取网站sitemap中所有链接,参数必须是sitemap的链接'''
22 | try:
23 | html = requests.get(url, timeout=5).text
24 | except:
25 | return 'miss'
26 | else:
27 | urls = re.findall('\s*?(.*?)\s*? ', html)
28 | return '\n'.join(urls)
29 |
30 |
31 | if __name__ == '__main__':
32 | url = 'http://data.zz.baidu.com/urls?site=tendcode.com&token=NpU01TxKEtTQAlBV'
33 | urls = get_urls('http://tendcode.com/sitemap.xml')
34 | r = push_urls(url,urls)
35 | print(r)
36 |
37 |
--------------------------------------------------------------------------------
/apps/tool/apis/common.py:
--------------------------------------------------------------------------------
1 | class OpenCode:
2 | # 函数执行超时,例如函数执行 requests 请求超时
3 | error_50000 = 50000
4 | # 函数执行错误,一般是未知异常,此时可以打印异常去定位原因
5 | error_50001 = 50001
6 | # 函数返回内容不合法,例如请求到的内容不符合返回体结构
7 | error_50002 = 50002
8 |
9 |
10 | class OpenApi(OpenCode):
11 | code = 0
12 | error = ""
13 | message = ""
14 | data = {}
15 |
16 | @property
17 | def body(self):
18 | resp = {
19 | "code": self.code, # 业务返回码,非0失败
20 | "error": self.error, # 错误提示,面向用户
21 | "message": self.message, # 错误提示,面向开发者
22 | "data": self.data # 返回数据,字典
23 | }
24 | return resp
25 |
26 |
27 | if __name__ == '__main__':
28 | op = OpenApi()
29 | op.code = 1
30 | op.data = [{"name": "izone"}]
31 | print(op.body)
32 | print(op.error_50000)
33 |
--------------------------------------------------------------------------------
/apps/tool/apis/useragent.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from user_agent import generate_user_agent
3 |
4 |
5 | def get_user_agent(os=None, navigator=None, device_type=None):
6 | try:
7 | u = generate_user_agent(os=os, navigator=navigator, device_type=device_type)
8 | except Exception as e:
9 | u = str(e)
10 | return u
11 |
12 |
13 | if __name__ == '__main__':
14 | get_user_agent()
15 |
--------------------------------------------------------------------------------
/apps/tool/apis/word_cloud.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | from collections import Counter
4 |
5 | import jieba
6 |
7 | # 只显示前N个词
8 | from .common import OpenApi
9 |
10 | MAX_WORD = 80
11 |
12 | root_path = os.path.dirname(__file__)
13 | stopwords_path = os.path.join(root_path, 'stopwords')
14 |
15 |
16 | def get_stop_words(stop_text, filename='ChineseStopWords.txt'):
17 | """读取指定停用词文件"""
18 | _fp = os.path.join(stopwords_path, filename)
19 | with open(_fp, 'r', encoding='utf-8') as f:
20 | lines = f.readlines()
21 | stop_words = [word.strip() for word in lines]
22 | if stop_text:
23 | input_stop_words = stop_text.strip().split('\n')
24 | if input_stop_words:
25 | stop_words.extend(input_stop_words)
26 | return stop_words
27 |
28 |
29 | def get_word_count(text, stop_text):
30 | """精确分词"""
31 | words = jieba.lcut(text)
32 | stop_words = get_stop_words(stop_text)
33 | new_words = [
34 | word for word in words if word not in stop_words and word.strip()
35 | ]
36 | # 停用纯数字
37 | if 'num-' in stop_words:
38 | new_words = [
39 | word for word in new_words if not re.findall(r'^\d+$', word)
40 | ]
41 | # 停用长度为1的词
42 | if 'single-' in stop_words:
43 | new_words = [
44 | word for word in new_words if len(word) > 1
45 | ]
46 | c = Counter(new_words).most_common(MAX_WORD)
47 | result = [{'name': k, 'weight': v} for k, v in c]
48 | return result
49 |
50 |
51 | def jieba_word_cloud(text, stop_text=None):
52 | """成功返回200,失败500,可以将失败的报错输出到console日志"""
53 | op = OpenApi()
54 | try:
55 | result = get_word_count(text, stop_text)
56 | op.data = {"list": result, "total": len(result), "max": MAX_WORD}
57 | except Exception as e:
58 | op.code = op.error_50001
59 | op.error = "请求错误,未获得词频统计"
60 | op.message = e
61 | return op.body
62 |
63 |
64 | if __name__ == "__main__":
65 | fp = '/tmp/test.txt'
66 | with open(fp, 'r', encoding='utf-8') as f:
67 | tex = f.read().strip()
68 | print(jieba_word_cloud(tex, stop_text='\n词\nless-'))
69 |
--------------------------------------------------------------------------------
/apps/tool/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ToolConfig(AppConfig):
5 | name = 'tool'
6 | verbose_name = '工具管理'
7 |
--------------------------------------------------------------------------------
/apps/tool/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.27 on 2023-03-13 17:43
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='ToolCategory',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('name', models.CharField(max_length=20, verbose_name='网站分类名称')),
20 | ('order_num', models.IntegerField(default=99, help_text='序号可以用来调整顺序,越小越靠前', verbose_name='序号')),
21 | ('icon', models.CharField(blank=True, default='fa fa-link', max_length=50, null=True, verbose_name='图标')),
22 | ],
23 | options={
24 | 'verbose_name': '工具分类',
25 | 'verbose_name_plural': '工具分类',
26 | 'ordering': ['order_num', 'id'],
27 | },
28 | ),
29 | migrations.CreateModel(
30 | name='ToolLink',
31 | fields=[
32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
33 | ('name', models.CharField(max_length=20, verbose_name='网站名称')),
34 | ('description', models.CharField(max_length=100, verbose_name='网站描述')),
35 | ('link', models.URLField(verbose_name='网站链接')),
36 | ('order_num', models.IntegerField(default=99, help_text='序号可以用来调整顺序,越小越靠前', verbose_name='序号')),
37 | ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='tool.ToolCategory', verbose_name='网站分类')),
38 | ],
39 | options={
40 | 'verbose_name': '推荐工具',
41 | 'verbose_name_plural': '推荐工具',
42 | 'ordering': ['order_num', 'id'],
43 | },
44 | ),
45 | ]
46 |
--------------------------------------------------------------------------------
/apps/tool/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/migrations/__init__.py
--------------------------------------------------------------------------------
/apps/tool/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | # Create your models here.
5 |
6 | class ToolCategory(models.Model):
7 | name = models.CharField('网站分类名称', max_length=20)
8 | order_num = models.IntegerField('序号', default=99, help_text='序号可以用来调整顺序,越小越靠前')
9 | icon = models.CharField('图标', max_length=50, blank=True, null=True, default='fa fa-link')
10 |
11 | class Meta:
12 | verbose_name = '工具分类'
13 | verbose_name_plural = verbose_name
14 | ordering = ['order_num', 'id']
15 |
16 | def __str__(self):
17 | return self.name
18 |
19 |
20 | class ToolLink(models.Model):
21 | name = models.CharField('网站名称', max_length=20)
22 | description = models.CharField('网站描述', max_length=100)
23 | link = models.URLField('网站链接')
24 | order_num = models.IntegerField('序号', default=99, help_text='序号可以用来调整顺序,越小越靠前')
25 | category = models.ForeignKey(ToolCategory, verbose_name='网站分类', blank=True, null=True,
26 | on_delete=models.SET_NULL)
27 |
28 | class Meta:
29 | verbose_name = '推荐工具'
30 | verbose_name_plural = verbose_name
31 | ordering = ['order_num', 'id']
32 |
33 | def __str__(self):
34 | return self.name
35 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/editormd-logo.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/editormd-logo.eot
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/editormd-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Generated by IcoMoon
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/editormd-logo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/editormd-logo.ttf
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/editormd-logo.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/editormd-logo.woff
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/apps/tool/static/editor/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/apps/tool/static/editor/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/images/loading.gif
--------------------------------------------------------------------------------
/apps/tool/static/editor/images/loading@2x.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/images/loading@2x.gif
--------------------------------------------------------------------------------
/apps/tool/static/editor/images/logos/editormd-favicon-16x16.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/images/logos/editormd-favicon-16x16.ico
--------------------------------------------------------------------------------
/apps/tool/static/editor/images/logos/editormd-logo-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/editor/images/logos/editormd-logo-96x96.png
--------------------------------------------------------------------------------
/apps/tool/static/editor/lib/codemirror/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2014 by Marijn Haverbeke and others
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/lib/codemirror/README.md:
--------------------------------------------------------------------------------
1 | # CodeMirror
2 | [](https://travis-ci.org/codemirror/CodeMirror)
3 | [](https://www.npmjs.org/package/codemirror)
4 | [Funding status: ](https://marijnhaverbeke.nl/fund/)
5 |
6 | CodeMirror is a JavaScript component that provides a code editor in
7 | the browser. When a mode is available for the language you are coding
8 | in, it will color your code, and optionally help with indentation.
9 |
10 | The project page is http://codemirror.net
11 | The manual is at http://codemirror.net/doc/manual.html
12 | The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
13 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/lib/codemirror/addon/dialog/dialog.css:
--------------------------------------------------------------------------------
1 | .CodeMirror-dialog {
2 | position: absolute;
3 | left: 0; right: 0;
4 | background: white;
5 | z-index: 15;
6 | padding: .1em .8em;
7 | overflow: hidden;
8 | color: #333;
9 | }
10 |
11 | .CodeMirror-dialog-top {
12 | border-bottom: 1px solid #eee;
13 | top: 0;
14 | }
15 |
16 | .CodeMirror-dialog-bottom {
17 | border-top: 1px solid #eee;
18 | bottom: 0;
19 | }
20 |
21 | .CodeMirror-dialog input {
22 | border: none;
23 | outline: none;
24 | background: transparent;
25 | width: 20em;
26 | color: inherit;
27 | font-family: monospace;
28 | }
29 |
30 | .CodeMirror-dialog button {
31 | font-size: 70%;
32 | }
33 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/lib/codemirror/addon/search/matchesonscrollbar.css:
--------------------------------------------------------------------------------
1 | .CodeMirror-search-match {
2 | background: gold;
3 | border-top: 1px solid orange;
4 | border-bottom: 1px solid orange;
5 | -moz-box-sizing: border-box;
6 | box-sizing: border-box;
7 | opacity: .5;
8 | }
9 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/lib/codemirror/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codemirror",
3 | "version":"5.0.0",
4 | "main": ["lib/codemirror.js", "lib/codemirror.css"],
5 | "ignore": [
6 | "**/.*",
7 | "node_modules",
8 | "components",
9 | "bin",
10 | "demo",
11 | "doc",
12 | "test",
13 | "index.html",
14 | "package.json"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/lib/codemirror/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codemirror",
3 | "version":"5.0.0",
4 | "main": "lib/codemirror.js",
5 | "description": "In-browser code editing made bearable",
6 | "licenses": [{"type": "MIT",
7 | "url": "http://codemirror.net/LICENSE"}],
8 | "directories": {"lib": "./lib"},
9 | "scripts": {"test": "node ./test/run.js"},
10 | "devDependencies": {"node-static": "0.6.0",
11 | "phantomjs": "1.9.2-5",
12 | "blint": ">=0.1.1"},
13 | "bugs": "http://github.com/codemirror/CodeMirror/issues",
14 | "keywords": ["JavaScript", "CodeMirror", "Editor"],
15 | "homepage": "http://codemirror.net",
16 | "maintainers":[{"name": "Marijn Haverbeke",
17 | "email": "marijnh@gmail.com",
18 | "web": "http://marijnhaverbeke.nl"}],
19 | "repository": {"type": "git",
20 | "url": "https://github.com/codemirror/CodeMirror.git"}
21 | }
22 |
--------------------------------------------------------------------------------
/apps/tool/static/editor/plugins/test-plugin/test-plugin.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Test plugin for Editor.md
3 | *
4 | * @file test-plugin.js
5 | * @author pandao
6 | * @version 1.2.0
7 | * @updateTime 2015-03-07
8 | * {@link https://github.com/pandao/editor.md}
9 | * @license MIT
10 | */
11 |
12 | (function() {
13 |
14 | var factory = function (exports) {
15 |
16 | var $ = jQuery; // if using module loader(Require.js/Sea.js).
17 |
18 | exports.testPlugin = function(){
19 | alert("testPlugin");
20 | };
21 |
22 | exports.fn.testPluginMethodA = function() {
23 | /*
24 | var _this = this; // this == the current instance object of Editor.md
25 | var lang = _this.lang;
26 | var settings = _this.settings;
27 | var editor = this.editor;
28 | var cursor = cm.getCursor();
29 | var selection = cm.getSelection();
30 | var classPrefix = this.classPrefix;
31 |
32 | cm.focus();
33 | */
34 | //....
35 |
36 | alert("testPluginMethodA");
37 | };
38 |
39 | };
40 |
41 | // CommonJS/Node.js
42 | if (typeof require === "function" && typeof exports === "object" && typeof module === "object")
43 | {
44 | module.exports = factory;
45 | }
46 | else if (typeof define === "function") // AMD/CMD/Sea.js
47 | {
48 | if (define.amd) { // for Require.js
49 |
50 | define(["editormd"], function(editormd) {
51 | factory(editormd);
52 | });
53 |
54 | } else { // for Sea.js
55 | define(function(require) {
56 | var editormd = require("./../../editormd");
57 | factory(editormd);
58 | });
59 | }
60 | }
61 | else
62 | {
63 | factory(window.editormd);
64 | }
65 |
66 | })();
67 |
--------------------------------------------------------------------------------
/apps/tool/static/tool/css/json2go/common.css:
--------------------------------------------------------------------------------
1 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0}body{display:block;margin:8px;}code{font:14px/1.25em sans-serif;font-family:'Consolas','Menlo','Monaco','Courier New',monospace;padding:0 3px;}.intro{display:flex;}.intro > div{width:33.333%;}h1{font-size:34px;font-weight:bold;line-height:1.5em;}h2{font-size:24px;line-height:1.3em;margin-top:20px;}p{margin-top:20px;line-height:1.5em;}p:first-child{margin-top:0;}#brand{max-width:400px;max-height:150px;float:right;}table{width:100%;table-layout:fixed;}th{padding:15px;background:#375EAB;text-align:center;color:#FFF;font-size:20px;}th label{margin-left:1em;font-size:14px;cursor:pointer;}td{width:50%;vertical-align:top;}#input,#output{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;white-space:pre;width:100%;display:block;padding:3%;font:14px/1.5em 'Consolas','Menlo','Monaco','Courier New',monospace;outline:none;border:none;resize:vertical;height:80vh;overflow:scroll;tab-size:4;}#input{background:#ECF2F5;border-right:2px solid #AAA;}#output{background:#E0EBF5;}.clr-red{color:#CC0000;}.faulty-line{color:#C00;background:#FDD;font-weight:bold}.json-go-faulty-char{border:1px solid purple;}.copy{font-size:14px;padding:5px;background:#80808099;border-radius:5px;cursor:pointer;}.copy:hover{background:#808080cf;}@media (max-width:800px){.intro{flex-direction:column;}.intro > div{width:100%;}#brand{float:none;margin:20px auto;display:block;}}
--------------------------------------------------------------------------------
/apps/tool/static/tool/css/json2go/tomorrow.highlight.css:
--------------------------------------------------------------------------------
1 | .hljs-comment{color:#8e908c;}.hljs-variable,.hljs-attribute,.hljs-tag,.hljs-regexp,.ruby .hljs-constant,.xml .hljs-tag .hljs-title,.xml .hljs-pi,.xml .hljs-doctype,.html .hljs-doctype,.css .hljs-id,.css .hljs-class,.css .hljs-pseudo{color:#c82829;}.hljs-number,.hljs-preprocessor,.hljs-pragma,.hljs-built_in,.hljs-literal,.hljs-params,.hljs-constant{color:#f5871f;}.ruby .hljs-class .hljs-title,.css .hljs-rules .hljs-attribute{color:#eab700;}.hljs-string,.hljs-value,.hljs-inheritance,.hljs-header,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00;}.css .hljs-hexcolor{color:#3e999f;}.hljs-function,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword,.perl .hljs-sub,.javascript .hljs-title,.coffeescript .hljs-title{color:#4271ae;}.hljs-keyword,.javascript .hljs-function{color:#8959a8;}.hljs{display:block;overflow-x:auto;color:#4d4d4c;-webkit-text-size-adjust:none;}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:0.5;}
--------------------------------------------------------------------------------
/apps/tool/static/tool/css/tool.css:
--------------------------------------------------------------------------------
1 | .tool-cate .card-header strong{padding-bottom:12px;border-bottom:2px solid #00AAEE;}.tool-cate .card-header{border-bottom:2px solid #f0f0f0;padding-bottom:10px;}.tool-header img{max-width:5rem;}.tool-des{height:8rem;}.tool-des p{line-height:2;}.title-info{border-left:4px solid #17a2b8;}pre{border:none;background-color:#e4eaef;border-radius:3px;font-size:85%;padding:.5rem;}.re-result pre{margin-bottom:0;}.re-result p{margin-bottom:5px;}.tool-list a:hover{color:#222;}.tool-link-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.card ul{line-height:2}.tool-list > div:nth-of-type(5n+1) .tool-header{background:linear-gradient(220.55deg,#7CF7FFC9 0%,#4B73FFC9 100%);}.tool-list > div:nth-of-type(12n+2) .tool-header{background:linear-gradient(220.55deg,#FFED46C9 0%,#FF7EC7C9 100%);}.tool-list > div:nth-of-type(12n+3) .tool-header{background:linear-gradient(220.55deg,#8FFF85C9 0%,#39A0FFC9 100%);}.tool-list > div:nth-of-type(12n+4) .tool-header{background:linear-gradient(220.55deg,#8A88FBC9 0%,#D079EEC9 100%);}.tool-list > div:nth-of-type(12n+5) .tool-header{background:linear-gradient(220.55deg,#FFEB3AC9 0%,#4DEF8EC9 100%);}.tool-list > div:nth-of-type(12n+6) .tool-header{background:linear-gradient(220.55deg,#FFF500C9 0%,#FFB800C9 100%);}.tool-list > div:nth-of-type(12n+7) .tool-header{background:linear-gradient(220.55deg,#FFEAF6C9 0%,#FF9DE4C9 100%);}.tool-list > div:nth-of-type(12n+8) .tool-header{background:linear-gradient(220.55deg,#FFE6A4C9 0%,#AD8211C9 100%);}.tool-list > div:nth-of-type(12n+9) .tool-header{background:linear-gradient(220.55deg,#C5EDF5C9 0%,#4A879AC9 100%);}.tool-list > div:nth-of-type(12n+10) .tool-header{background:linear-gradient(220.55deg,#FFF6EBC9 0%,#DFD1C5C9 100%);}.tool-list > div:nth-of-type(12n+11) .tool-header{background:linear-gradient(220.55deg,#97E8B5C9 0%,#5CB67FC9 100%);}.tool-list > div:nth-of-type(12n+12) .tool-header{background:linear-gradient(220.55deg,#FF8570C9 0%,#418CB7C9 100%);}@media (min-width:1200px){.tool-list .card:hover{box-shadow:0 3px 9px rgba(0,0,0,0.275)}}
--------------------------------------------------------------------------------
/apps/tool/static/tool/img/HTML5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/tool/img/HTML5.png
--------------------------------------------------------------------------------
/apps/tool/static/tool/img/go.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/tool/img/go.ico
--------------------------------------------------------------------------------
/apps/tool/static/tool/img/golang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/tool/img/golang.png
--------------------------------------------------------------------------------
/apps/tool/static/tool/img/linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/tool/img/linux.png
--------------------------------------------------------------------------------
/apps/tool/static/tool/img/query_ip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/tool/img/query_ip.png
--------------------------------------------------------------------------------
/apps/tool/static/tool/img/tax128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/apps/tool/static/tool/img/tax128.png
--------------------------------------------------------------------------------
/apps/tool/templates/tool/base_tool.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 |
4 | {% block top-file %}
5 |
6 | {% endblock %}
7 |
8 | {% block base_content %}
9 |
10 |
11 |
12 |
13 |
14 |
15 | 首页
16 |
17 |
18 | 在线工具
19 |
20 | {% block tool_name %}{% endblock %}
21 |
22 |
23 |
24 | {% block left_content %}{% endblock %}
25 |
26 |
27 |
28 | {% include 'tool/tags/tool_list.html' %}
29 |
30 |
31 |
32 | {% endblock %}
33 |
34 | {% block end_file %}
35 |
36 | {% block end_f %}{% endblock %}
37 | {% endblock %}
--------------------------------------------------------------------------------
/apps/tool/templates/tool/linux_timeline.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 |
8 | Linux Timeline
9 |
10 |
11 |
12 |
13 | {% include 'tool/tags/ldt.html' %}
14 |
--------------------------------------------------------------------------------
/apps/tool/templates/tool/regex.html:
--------------------------------------------------------------------------------
1 | {% extends "tool/base_tool.html" %}
2 | {% load static %}
3 |
4 | {% block head_title %}正则表达式在线测试,常用正则表达式_在线工具{% endblock %}
5 | {% block metas %}
6 |
7 |
8 | {% endblock %}
9 |
10 | {% block tool_name %}在线正则表达式{% endblock %}
11 | {% block left_content %}
12 |
13 |
工具说明:
14 |
15 | 按照通用的正则表达式的规则填写表单即可提取信息
16 | 本工具使用Python的正则表达式库实现,支持Python正则表达式语法
17 |
18 |
19 |
20 |
21 | 待匹配信息:
22 |
23 |
24 |
25 | 正则表达式:
26 |
27 |
28 |
开始匹配
29 |
30 |
34 | {% endblock %}
35 |
36 | {% block end_f %}
37 |
45 | {% endblock %}
46 |
--------------------------------------------------------------------------------
/apps/tool/templates/tool/tags/github_corners.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/tool/templates/tool/tags/tool_item.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
{{ tool_item.desc }}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/tool/templates/tool/tool.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 | {% load humanize %}
4 | {% load blog_tags tool_tags %}
5 |
6 | {% block head_title %}在线工具,提升工作效率{% endblock %}
7 | {% block metas %}
8 |
9 |
10 | {% endblock %}
11 |
12 |
13 | {% block top-file %}
14 |
15 | {% endblock %}
16 |
17 | {% block base_content %}
18 |
19 |
20 | {% get_toollist_by_key as tool_list %}
21 | {% for tool_item in tool_list %}
22 | {% load_tool_item tool_item %}
23 | {% endfor %}
24 |
25 |
26 | {% endblock %}
27 |
28 | {% block end_file %}
29 | {#延迟加载markdown编辑器的静态文件#}
30 |
31 |
32 |
33 |
34 |
35 | {% endblock %}
--------------------------------------------------------------------------------
/apps/tool/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
--------------------------------------------------------------------------------
/apps/tool/templatetags/tool_tags.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django import template
3 | from django.db.models.aggregates import Count
4 | from django.templatetags.static import static
5 | from django.urls import reverse
6 |
7 | from ..models import ToolCategory
8 | from ..utils import IZONE_TOOLS
9 |
10 | register = template.Library()
11 |
12 |
13 | @register.simple_tag
14 | def get_toolcates():
15 | """获取所有工具分类,只显示有工具的分类"""
16 | return ToolCategory.objects.annotate(total_num=Count('toollink')).filter(
17 | total_num__gt=0)
18 |
19 |
20 | @register.simple_tag
21 | def get_toollinks(cate):
22 | """获取单个分类下所有工具"""
23 | return cate.toollink_set.all()
24 |
25 |
26 | @register.simple_tag
27 | def get_toollist_by_key(key=None):
28 | """返回工具列表"""
29 | tools = []
30 | if not key or key not in IZONE_TOOLS:
31 | for _k in IZONE_TOOLS:
32 | _tag = IZONE_TOOLS[_k]['tag']
33 | _tools = IZONE_TOOLS[_k]['tools']
34 | for each in _tools:
35 | item = {'tag': _tag,
36 | 'name': each['name'],
37 | 'url': reverse(each['url']),
38 | 'img': static(each['img']),
39 | 'desc': each['desc']}
40 | tools.append(item)
41 | else:
42 | _tag = IZONE_TOOLS[key]['tag']
43 | _tools = IZONE_TOOLS[key]['tools']
44 | for each in _tools:
45 | item = {'tag': _tag,
46 | 'name': each['name'],
47 | 'url': reverse(each['url']),
48 | 'img': static(each['img']),
49 | 'desc': each['desc']}
50 | tools.append(item)
51 | return tools
52 |
53 |
54 | @register.inclusion_tag('tool/tags/tool_item.html')
55 | def load_tool_item(item):
56 | """返回单个工具显示栏"""
57 | return {'tool_item': item}
58 |
59 |
60 | @register.inclusion_tag('tool/tags/github_corners.html')
61 | def load_github_corners(position, color, url):
62 | """
63 | 加载github项目跳转,根据颜色返回
64 | """
65 | return {'position': position, 'color': color, 'url': url}
66 |
--------------------------------------------------------------------------------
/apps/tool/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/apps/tool/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.urls import path
3 | from .views import (Toolview, BD_pushview, BD_pushview_site,
4 | regexview, useragent_view, html_characters,
5 | docker_search_view, editor_view, word_cloud,
6 | json2go, tax, query_ip, linux_timeline,
7 | )
8 |
9 | urlpatterns = [
10 | path('', Toolview, name='total'), # 工具汇总页
11 | path('baidu-linksubmit/', BD_pushview, name='baidu_push'), # 百度主动推送
12 | path('baidu-linksubmit-sitemap/', BD_pushview_site, name='baidu_push_site'), # 百度主动推送sitemap
13 | path('regex/', regexview, name='regex'), # 正则表达式在线
14 | path('user-agent/', useragent_view, name='useragent'), # user-agent生成器
15 | path('html-special-characters/', html_characters, name='html_characters'), # HTML特殊字符查询
16 | path('docker-search/', docker_search_view, name='docker_search'), # docker镜像查询
17 | path('markdown-editor/', editor_view, name='markdown_editor'), # editor.md 工具
18 | path('word-cloud/', word_cloud, name='word_cloud'), # 词云图 工具
19 | path('json2go/', json2go, name='json2go'), # json转go
20 | path('tax/', tax, name='tax'), # 个人所得税年度汇算
21 | path('ip/', query_ip, name='ip'), # 查询IP
22 | path('linux-timeline/', linux_timeline, name='linux_timeline'),
23 | ]
24 |
--------------------------------------------------------------------------------
/izone/__init__.py:
--------------------------------------------------------------------------------
1 | from .celery import app as celery_app
2 |
3 | __all__ = ('celery_app',)
4 |
--------------------------------------------------------------------------------
/izone/celery.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | import os
3 | from celery import Celery
4 |
5 | # 设置环境变量
6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'izone.settings')
7 |
8 | # 实例化
9 | app = Celery('izone')
10 |
11 | # namespace='CELERY'作用是允许你在Django配置文件中对Celery进行配置
12 | # 但所有Celery配置项必须以CELERY开头,防止冲突
13 | app.config_from_object('django.conf:settings', namespace='CELERY')
14 |
15 | # 自动从Django的已注册app中发现任务
16 | app.autodiscover_tasks()
17 |
--------------------------------------------------------------------------------
/izone/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for izone project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "izone.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/log/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/log/.gitkeep
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "izone.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError:
10 | # The above import may fail for some other reason. Ensure that the
11 | # issue is really that Django is missing to avoid masking other
12 | # exceptions on Python 2.
13 | try:
14 | import django
15 | except ImportError:
16 | raise ImportError(
17 | "Couldn't import Django. Are you sure it's installed and "
18 | "available on your PYTHONPATH environment variable? Did you "
19 | "forget to activate a virtual environment?"
20 | )
21 | raise
22 | execute_from_command_line(sys.argv)
23 |
--------------------------------------------------------------------------------
/media/article/default/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/article/default/default.png
--------------------------------------------------------------------------------
/media/avatar/default/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default.png
--------------------------------------------------------------------------------
/media/avatar/default/default1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default1.png
--------------------------------------------------------------------------------
/media/avatar/default/default10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default10.png
--------------------------------------------------------------------------------
/media/avatar/default/default2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default2.png
--------------------------------------------------------------------------------
/media/avatar/default/default3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default3.png
--------------------------------------------------------------------------------
/media/avatar/default/default4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default4.png
--------------------------------------------------------------------------------
/media/avatar/default/default5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default5.png
--------------------------------------------------------------------------------
/media/avatar/default/default6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default6.png
--------------------------------------------------------------------------------
/media/avatar/default/default7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default7.png
--------------------------------------------------------------------------------
/media/avatar/default/default8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default8.png
--------------------------------------------------------------------------------
/media/avatar/default/default9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/avatar/default/default9.png
--------------------------------------------------------------------------------
/media/friend/default/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/friend/default/default.png
--------------------------------------------------------------------------------
/media/subject/default/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/media/subject/default/default.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | amqp==2.6.1
2 | billiard==3.6.4.0
3 | bleach==3.3.0
4 | bootstrap-admin==0.4.3
5 | celery==4.4.2
6 | certifi==2022.12.7
7 | chardet==3.0.4
8 | defusedxml==0.6.0
9 | Django==2.2.28
10 | django-allauth==0.42.0
11 | django-appconf==1.0.3
12 | django-celery-beat==2.2.0
13 | django-celery-results==2.0.1
14 | django-crispy-forms==1.7.2
15 | django-haystack==2.8.1
16 | django-imagekit==4.0.2
17 | django-redis==4.10.0
18 | django-tctip==1.4.7
19 | django-timezone-field==4.2.3
20 | djangorestframework==3.11.2
21 | django-webstack>=1.5.4
22 | gunicorn==19.9.0
23 | html5lib==1.0.1
24 | idna==2.8
25 | importlib-metadata==6.6.0
26 | jieba==0.39
27 | kombu==4.6.11
28 | Markdown==3.4.3
29 | markdown-checklist==0.4.4
30 | mysqlclient==2.0.3
31 | oauthlib==3.1.0
32 | olefile==0.46
33 | packaging==21.3
34 | pilkit==2.0
35 | Pillow==9.3.0
36 | pycryptodome==3.20.0
37 | Pygments==2.15.1
38 | PyMySQL==1.0.2
39 | pyparsing==3.0.7
40 | python-crontab==2.7.1
41 | python-dateutil==2.8.2
42 | python3-openid==3.1.0
43 | pytz==2019.2
44 | redis==3.3.8
45 | requests==2.22.0
46 | requests-oauthlib==1.2.0
47 | setuptools-scm==6.0.1
48 | six==1.12.0
49 | sqlparse==0.3.0
50 | supervisor==4.2.5
51 | urllib3==1.25.3
52 | user-agent==0.1.9
53 | vine==1.3.0
54 | webencodings==0.5.1
55 | Whoosh==2.7.4
56 | zipp==3.15.0
57 | sgmllib3k==1.0.0
58 | feedparser==6.0.11
59 |
--------------------------------------------------------------------------------
/supervisord.conf:
--------------------------------------------------------------------------------
1 | [supervisord]
2 | logfile=log/supervisord.log ; main log file; default $CWD/supervisord.log
3 | pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid
4 |
5 | [unix_http_server]
6 | file=/tmp/supervisor.sock ; the path to the socket file
7 |
8 | [rpcinterface:supervisor]
9 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
10 |
11 | [supervisorctl]
12 | serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
13 |
14 | [program:gunicorn-django]
15 | command=gunicorn izone.wsgi -b 0.0.0.0:8000
16 | directory=/opt/cloud/izone
17 | stdout_logfile=log/gunicorn.django.log
18 | stderr_logfile=log/gunicorn.django.log
19 | autostart=true
20 | autorestart=true
21 | startsecs=2
22 | stopwaitsecs=2
23 | priority=100
24 |
25 | [program:celery-worker]
26 | command=celery -A izone worker -l info
27 | directory=/opt/cloud/izone
28 | stdout_logfile=log/celery.worker.log
29 | stderr_logfile=log/celery.worker.log
30 | autostart=true
31 | autorestart=true
32 | startsecs=3
33 | stopwaitsecs=3
34 | priority=102
35 |
36 | [program:celery-beat]
37 | command=celery -A izone beat -l info
38 | directory=/opt/cloud/izone
39 | stdout_logfile=log/celery.beat.log
40 | stderr_logfile=log/celery.beat.log
41 | autostart=true
42 | autorestart=true
43 | startsecs=2
44 | stopwaitsecs=2
45 | priority=101
--------------------------------------------------------------------------------
/templates/403.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 |
4 | {% block head_title %}403{% endblock %}
5 | {% block metas %}
6 |
7 |
8 | {% endblock %}
9 |
10 | {% block base_content %}
11 |
12 |
13 |
14 |
403
15 |
16 |
😠你没有权限造访本星球,请返回地球...
17 |
返回地球
18 |
19 |
20 |
21 |
22 | {% endblock %}
--------------------------------------------------------------------------------
/templates/404.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 |
4 | {% block head_title %}404{% endblock %}
5 | {% block metas %}
6 |
7 |
8 | {% endblock %}
9 |
10 | {% block base_content %}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
😔你好像访问到了异次元世界...
19 |
返回地球
20 |
21 |
22 |
23 |
24 | {% endblock %}
--------------------------------------------------------------------------------
/templates/500.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static %}
3 |
4 | {% block head_title %}500{% endblock %}
5 | {% block metas %}
6 |
7 |
8 | {% endblock %}
9 |
10 | {% block base_content %}
11 |
12 |
13 |
14 |
500
15 |
16 |
‼️当前页面功能异常,紧急修复中...
17 |
返回地球
18 |
19 |
20 |
21 |
22 | {% endblock %}
--------------------------------------------------------------------------------
/templates/account/account_inactive.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Account Inactive" %}{% endblock %}
6 | {% block user_title %}{% trans "Account Inactive" %}{% endblock %}
7 |
8 | {% block content %}
9 | {% trans "This account is inactive." %}
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/templates/account/base.html:
--------------------------------------------------------------------------------
1 | {% extends "blog/base.html" %}
2 | {% load static blog_tags %}
3 |
4 | {% block metas %}
5 |
6 |
7 | {% endblock %}
8 |
9 | {% block top-file %}
10 |
11 | {% endblock %}
12 |
13 | {% block base_content %}
14 |
15 |
16 |
17 |
18 |
21 |
{% block content %}{% endblock %}
22 |
23 |
24 | 快速登录
25 |
26 |
27 | {% get_request_param request 'next' as next_url %}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | {% endblock %}
37 |
38 | {% block end_file %}
39 | {% block extra_body %}
40 | {% endblock %}
41 | {% endblock %}
--------------------------------------------------------------------------------
/templates/account/email/password_reset_key_message.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans with site_name=current_site.name site_domain=current_site.domain %}
3 | 来自 {{ site_name }} 的问候!
4 |
5 | 您收到此电子邮件是因为您或其他人为您的用户帐户请求了密码重置。如果您未要求重置密码,则可以安全地忽略它。 若您需要重置密码,请点击下方的链接:
6 | {% endblocktrans %}
7 | {{ password_reset_url }}
8 |
9 | {% if username %}{% blocktrans %}In case you forgot, your username is {{ username }}.{% endblocktrans %}
10 |
11 | {% endif %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}感谢你使用 {{ site_name }}!
12 | {{ site_domain }}{% endblocktrans %}
13 |
--------------------------------------------------------------------------------
/templates/account/email_confirm.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load account %}
5 |
6 | {% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %}
7 | {% block user_title %}{% trans "Confirm E-mail Address" %}{% endblock %}
8 |
9 |
10 | {% block content %}
11 |
12 | {% if confirmation %}
13 |
14 | {% user_display confirmation.email_address.user as user_display %}
15 |
16 | {% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}
17 |
18 |
22 |
23 | {% else %}
24 |
25 | {% url 'account_email' as email_url %}
26 |
27 | {% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request .{% endblocktrans %}
28 |
29 | {% endif %}
30 |
31 | {% endblock %}
32 |
--------------------------------------------------------------------------------
/templates/account/login.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load account socialaccount %}
5 | {% load static %}
6 | {% load crispy_forms_tags %}
7 |
8 | {% block head_title %}{% trans "Sign In" %}{% endblock %}
9 | {% block user_title %}{% trans "Sign In" %}{% endblock %}
10 |
11 | {% block content %}
12 |
21 |
22 | {% endblock %}
23 |
--------------------------------------------------------------------------------
/templates/account/logout.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Sign Out" %}{% endblock %}
6 | {% block user_title %}{% trans "Sign Out" %}{% endblock %}
7 |
8 | {% block content %}
9 | {% trans 'Are you sure you want to sign out?' %}
10 |
11 |
18 |
19 |
20 | {% endblock %}
21 |
--------------------------------------------------------------------------------
/templates/account/password_change.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load crispy_forms_tags %}
5 |
6 | {% block head_title %}{% trans "Change Password" %}{% endblock %}
7 | {% block user_title %}{% trans "Change Password" %}{% endblock %}
8 |
9 | {% block content %}
10 |
15 | {% endblock %}
16 |
--------------------------------------------------------------------------------
/templates/account/password_reset.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load account %}
5 | {% load crispy_forms_tags %}
6 |
7 | {% block head_title %}{% trans "Password Reset" %}{% endblock %}
8 | {% block user_title %}{% trans "Password Reset" %}{% endblock %}
9 |
10 | {% block content %}
11 |
12 | {% if user.is_authenticated %}
13 | {% include "account/snippets/already_logged_in.html" %}
14 | {% endif %}
15 |
16 | {% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
17 |
18 |
23 |
24 | {% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}
25 | {% endblock %}
26 |
--------------------------------------------------------------------------------
/templates/account/password_reset_done.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load account %}
5 |
6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %}
7 | {% block user_title %}{% trans "Password Reset" %}{% endblock %}
8 |
9 | {% block content %}
10 |
11 | {% if user.is_authenticated %}
12 | {% include "account/snippets/already_logged_in.html" %}
13 | {% endif %}
14 |
15 | {% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
16 | {% endblock %}
17 |
--------------------------------------------------------------------------------
/templates/account/password_reset_from_key.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load crispy_forms_tags %}
5 | {% block head_title %}{% trans "Change Password" %}{% endblock %}
6 | {% block user_title %}{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}{% endblock %}
7 |
8 | {% block content %}
9 | {% if token_fail %}
10 | {% url 'account_reset_password' as passwd_reset_url %}
11 | {% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset .{% endblocktrans %}
12 | {% else %}
13 | {% if form %}
14 |
19 | {% else %}
20 | {% trans 'Your password is now changed.' %}
21 | {% endif %}
22 | {% endif %}
23 | {% endblock %}
24 |
--------------------------------------------------------------------------------
/templates/account/password_reset_from_key_done.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% block head_title %}{% trans "Change Password" %}{% endblock %}
5 | {% block user_title %}{% trans "Change Password" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans 'Your password is now changed.' %}
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/templates/account/password_set.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load crispy_forms_tags %}
5 |
6 | {% block head_title %}{% trans "Set Password" %}{% endblock %}
7 | {% block user_title %}{% trans "Set Password" %}{% endblock %}
8 |
9 | {% block content %}
10 |
15 | {% endblock %}
16 |
--------------------------------------------------------------------------------
/templates/account/signup.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load crispy_forms_tags %}
5 |
6 | {% block head_title %}{% trans "Signup" %}{% endblock %}
7 |
8 | {% block user_title %}{% trans "Signup" %}{% endblock %}
9 | {% block content %}
10 |
11 |
12 |
21 |
22 | {% endblock %}
23 |
--------------------------------------------------------------------------------
/templates/account/signup_closed.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}
6 | {% block user_title %}{% trans "Sign Up Closed" %}{% endblock %}
7 |
8 | {% block content %}
9 | {% trans "We are sorry, but the sign up is currently closed." %}
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/templates/account/verification_sent.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}
6 | {% block user_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}
7 |
8 | {% block content %}
9 | {% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
10 |
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/templates/account/verified_email_required.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}
6 | {% block user_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}
7 |
8 | {% block content %}
9 |
10 | {% url 'account_email' as email_url %}
11 |
12 | {% blocktrans %}This part of the site requires us to verify that
13 | you are who you claim to be. For this purpose, we require that you
14 | verify ownership of your e-mail address. {% endblocktrans %}
15 |
16 | {% blocktrans %}We have sent an e-mail to you for
17 | verification. Please click on the link inside this e-mail. Please
18 | contact us if you do not receive it within a few minutes.{% endblocktrans %}
19 |
20 | {% blocktrans %}Note: you can still change your e-mail address .{% endblocktrans %}
21 |
22 |
23 | {% endblock %}
24 |
--------------------------------------------------------------------------------
/templates/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /adminx/
3 | Disallow: /accounts/
4 | Disallow: /comment/
5 | Disallow: /feed/
6 | Disallow: /search/
7 | Disallow: /silian.xml
8 | Disallow: /resume/
9 |
10 | Sitemap: {{ site_url }}/sitemap.xml
11 |
--------------------------------------------------------------------------------
/templates/search/indexes/blog/article_text.txt:
--------------------------------------------------------------------------------
1 | {{ object.title }}
2 | {{ object.body_to_markdown }}
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hopetree/izone/db9a9071e4fde9de8a8f85b1d785e63ea464c812/utils/__init__.py
--------------------------------------------------------------------------------