├── Workspace ├── .keep ├── runtime │ ├── .keep │ └── config.json ├── static │ ├── .keep │ ├── img │ │ ├── .keep │ │ ├── corpus │ │ │ └── .keep │ │ ├── instagram │ │ │ └── .keep │ │ ├── favicon.png │ │ ├── head_128.png │ │ ├── Calatrava.png │ │ ├── background.jpg │ │ ├── postman_128.png │ │ ├── background_me.jpg │ │ ├── bilibili │ │ │ └── head.jpg │ │ ├── donate-alipay.jpg │ │ ├── donate-wechat.jpg │ │ └── background_index.jpg │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── css │ │ ├── height.css │ │ └── me.css │ └── js │ │ ├── buttons.js │ │ └── me.js └── templates │ ├── .keep │ ├── corpus │ └── .keep │ ├── posts │ └── .keep │ ├── footer_bar.html │ ├── search_result_posts_cell.html │ ├── search_result_corpus_cell.html │ ├── search_result_project_cell.html │ ├── update_corpus_cell.html │ ├── update_posts_cell.html │ ├── update_project_cell.html │ ├── error_notsupport.html │ ├── search_result_instagram_cell.html │ ├── update_instagram_cell.html │ ├── error_404.html │ ├── navigation_bar.html │ ├── search_result_bilibili_cell.html │ ├── update_bilibili_cell.html │ ├── index.html │ ├── search.html │ ├── posts_archive.html │ ├── posts_search.html │ ├── modules.html │ ├── corpus_list.html │ ├── project.html │ └── corpus_posts_list.html ├── Script ├── build_debug.sh ├── clean_build.sh ├── build_release.sh ├── run_debug.sh ├── clean_all.sh ├── run_release.sh ├── env │ └── ubuntu_16_04.sh └── xcodeproj.sh ├── Assets ├── Calatrava.png └── Calatrava.psd ├── Source └── Calatrava │ ├── main.swift │ ├── Base │ ├── MonitorHandle.swift │ ├── FooterBarView.swift │ ├── NavigationBarView.swift │ ├── Global.swift │ ├── AppConfig.swift │ ├── Extension.swift │ ├── ConfigModel.swift │ └── EventHooks.swift │ ├── Modules │ ├── Posts │ │ ├── PostsOldHandle.swift │ │ ├── PostsTextView.swift │ │ ├── PostsHistoryModel.swift │ │ ├── PostsSearchView.swift │ │ ├── PostsCommentModel.swift │ │ ├── PostsTagModel.swift │ │ ├── PostsArchiveView.swift │ │ ├── PostsLoveHandle.swift │ │ ├── PostsModel.swift │ │ ├── PostsView.swift │ │ ├── PostsCommentHandle.swift │ │ └── PostsListView.swift │ ├── Report │ │ ├── ReportOnlyDateModel.swift │ │ └── ReportTotalView.swift │ ├── Corpus │ │ ├── CorpusPostsTextView.swift │ │ ├── CorpusModel.swift │ │ ├── CorpusPostsModel.swift │ │ ├── CorpusPostsCommentModel.swift │ │ ├── CorpusPostsLoveHandle.swift │ │ ├── CorpusListView.swift │ │ ├── CorpusPostsListView.swift │ │ ├── CorpusPostsView.swift │ │ └── CorpusPostsCommentHandle.swift │ ├── VPSSSCURL │ │ └── VPSSSCURL.swift │ ├── Base │ │ ├── VerificationCode │ │ │ ├── VerificationHandle.swift │ │ │ └── VerificationManager.swift │ │ └── Statistics │ │ │ ├── StatisticsManager.swift │ │ │ └── VisitStatisticsModel.swift │ ├── Search │ │ ├── SearchView.swift │ │ ├── SearchResultPostsView.swift │ │ ├── SearchResultProjectView.swift │ │ ├── SearchResultInstagramView.swift │ │ ├── SearchResultCorpusModel.swift │ │ └── SearchResultBilibiliView.swift │ ├── Update │ │ ├── UpdatePostsView.swift │ │ ├── UpdateProjectView.swift │ │ ├── UpdateInstagramModel.swift │ │ ├── UpdateCorpusModel.swift │ │ ├── UpdateBilibiliModel.swift │ │ ├── UpdateModel.swift │ │ └── UpdateListView.swift │ ├── About │ │ ├── MessageModel.swift │ │ ├── AboutView.swift │ │ └── MessageHandle.swift │ ├── Bilibili │ │ ├── BilibiliListModel.swift │ │ └── BilibiliFeedModel.swift │ ├── Project │ │ ├── ProjectModel.swift │ │ └── ProjectListView.swift │ ├── Instagram │ │ ├── InstagramUserModel.swift │ │ ├── InstagramFeedModel.swift │ │ ├── InstagramCurlHandle.swift │ │ └── InstagramListView.swift │ ├── Index │ │ └── IndexView.swift │ └── Modules │ │ ├── ModuleListView.swift │ │ └── ModuleModel.swift │ ├── Plugin │ ├── NotFoundFilterPlugin.swift │ ├── ReportGeneratePlugin.swift │ ├── ReportUpdatePlugin.swift │ ├── DailyCleanPlugin.swift │ └── InstagramTimerPlugin.swift │ └── Error │ ├── ErrorNotSupportView.swift │ └── ErrorNotFoundView.swift ├── ISSUE_TEMPLATE.md ├── Package.swift ├── .gitignore ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md └── README.md /Workspace/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/runtime/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/static/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/static/img/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/templates/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/static/img/corpus/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/templates/corpus/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/templates/posts/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Workspace/static/img/instagram/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Script/build_debug.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | swift build -------------------------------------------------------------------------------- /Script/clean_build.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | swift package clean -------------------------------------------------------------------------------- /Script/build_release.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | swift build -c release -------------------------------------------------------------------------------- /Script/run_debug.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | lldb ./.build/debug/Calatrava -------------------------------------------------------------------------------- /Script/clean_all.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | rm -rf .build 3 | rm Package.resolved 4 | -------------------------------------------------------------------------------- /Assets/Calatrava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Assets/Calatrava.png -------------------------------------------------------------------------------- /Assets/Calatrava.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Assets/Calatrava.psd -------------------------------------------------------------------------------- /Workspace/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/favicon.png -------------------------------------------------------------------------------- /Workspace/static/img/head_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/head_128.png -------------------------------------------------------------------------------- /Workspace/static/img/Calatrava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/Calatrava.png -------------------------------------------------------------------------------- /Workspace/static/img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/background.jpg -------------------------------------------------------------------------------- /Workspace/static/img/postman_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/postman_128.png -------------------------------------------------------------------------------- /Workspace/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /Workspace/static/img/background_me.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/background_me.jpg -------------------------------------------------------------------------------- /Workspace/static/img/bilibili/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/bilibili/head.jpg -------------------------------------------------------------------------------- /Workspace/static/img/donate-alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/donate-alipay.jpg -------------------------------------------------------------------------------- /Workspace/static/img/donate-wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/donate-wechat.jpg -------------------------------------------------------------------------------- /Workspace/static/img/background_index.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/img/background_index.jpg -------------------------------------------------------------------------------- /Workspace/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /Workspace/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /Workspace/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /Workspace/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enums/Calatrava/HEAD/Workspace/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /Script/run_release.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | while true 3 | do 4 | ./.build/release/Calatrava 5 | DATE=`date +%Y-%m-%d_%H:%M:%S` 6 | echo '['$DATE']Crash detected!' >> Workspace/runtime/crash.log 7 | done 8 | -------------------------------------------------------------------------------- /Source/Calatrava/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/24. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | PjangoRuntime.run(delegate: AppDelegate.init()) 13 | 14 | -------------------------------------------------------------------------------- /Script/env/ubuntu_16_04.sh: -------------------------------------------------------------------------------- 1 | sudo apt update 2 | sudo apt install git 3 | git clone https://github.com/enums/Perfect-Ubuntu.git 4 | cd Perfect-Ubuntu/ 5 | sudo ./install.sh --sure 6 | sudo apt install -y mysql-client-core-5.7 mysql-client-5.7 mysql-server-core-5.7 mysql-server-core-5.7 mysql-server-5.7 7 | echo "done" -------------------------------------------------------------------------------- /Source/Calatrava/Base/MonitorHandle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MonitorHandle.swift 3 | // Calatrava 4 | // 5 | // Created by enum on 2019/3/26. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | func monitorHandle() -> PCUrlHandle { 12 | return pjangoHttpResponse { req, res in 13 | pjangoHttpResponse("1")(req, res) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Script/xcodeproj.sh: -------------------------------------------------------------------------------- 1 | cd ../ 2 | swift package generate-xcodeproj 3 | open ./Calatrava.xcodeproj 4 | echo "Tips:" 5 | echo "1. 编辑 module.modulemap. 设置你的真实头文件路径,例: /usr/local/mysql/include/mysql.h" 6 | echo "2. Target -> PerfectMySQL -> Build Settings -> Library Search Paths 添加 /usr/local/mysql/lib" 7 | echo "3. Target -> PjangoMySQL -> Build Settings -> Other Linker Flags 添加 -L/usr/local/mysql/lib" 8 | -------------------------------------------------------------------------------- /Source/Calatrava/Base/FooterBarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FooterBarView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/24. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class FooterBarView: PCDetailView { 13 | 14 | override var templateName: String? { 15 | return "footer_bar.html" 16 | } 17 | 18 | static var html = FooterBarView.meta.getTemplate() 19 | } 20 | -------------------------------------------------------------------------------- /Workspace/runtime/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "macos_workspace_path": "", 3 | "workspace_path": "", 4 | 5 | "log_path": "runtime/calatrava.log", 6 | 7 | "base_dir": "", 8 | "template_dir": "templates", 9 | "static_dir": "static", 10 | 11 | "port": 80, 12 | "log_debug": false, 13 | 14 | "mysql_schema": "Pjango_calatrava", 15 | "mysql_user": "", 16 | "mysql_password": "", 17 | "mysql_host": "127.0.0.1", 18 | "mysql_port": 3306 19 | } -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Posts/PostsOldHandle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostsOldHandle.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/26. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | func postsOldHandle() -> PCUrlHandle { 13 | return { req, res in 14 | let pid = Int(req.getUrlParam(key: "pid") ?? "-1") ?? -1 15 | pjangoHttpRedirect(url: "http://\(WEBSITE_HOST)/posts/article/\(pid)")(req, res) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Report/ReportOnlyDateModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReportOnlyDateModel.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2018/6/19. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | class ReportOnlyDateModel: PCModel { 12 | 13 | var date: String 14 | var selected = false 15 | 16 | init(date: String) { 17 | self.date = date 18 | } 19 | 20 | required init() { 21 | fatalError("init() has not been implemented") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Corpus/CorpusPostsTextView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CorpusPostsTextView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/12/30. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | class CorpusTextView: PCDetailView { 12 | 13 | var cpid: Int 14 | 15 | override var templateName: String? { 16 | return "corpus/\(cpid).html" 17 | } 18 | 19 | init(cpid: Int) { 20 | self.cpid = cpid 21 | } 22 | 23 | required init() { 24 | self.cpid = -1 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Posts/PostsTextView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostsTextView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/25. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class PostsTextView: PCDetailView { 13 | 14 | var pid: Int 15 | 16 | override var templateName: String? { 17 | return "posts/\(pid).html" 18 | } 19 | 20 | init(pid: Int) { 21 | self.pid = pid 22 | } 23 | 24 | required init() { 25 | self.pid = -1 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Workspace/templates/footer_bar.html: -------------------------------------------------------------------------------- 1 | 17 |
-------------------------------------------------------------------------------- /Source/Calatrava/Base/NavigationBarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationBarView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/24. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class NavigationBarView: PCDetailView { 13 | 14 | override var templateName: String? { 15 | return "navigation_bar.html" 16 | } 17 | 18 | override var viewParam: PCViewParam? { 19 | return [ 20 | "_pjango_param_host": WEBSITE_HOST, 21 | ] 22 | } 23 | 24 | static var html = NavigationBarView.meta.getTemplate() 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Source/Calatrava/Plugin/NotFoundFilterPlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotFoundFilterPlugin.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/25. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import PerfectHTTP 11 | import Pjango 12 | 13 | class NotFoundFilterPlugin: PCHTTPFilterPlugin { 14 | 15 | override func responseFilterHeader(req: HTTPRequest, res: HTTPResponse) -> Bool { 16 | if case .notFound = res.status { 17 | ErrorNotFoundView.asHandle()(req, res) 18 | return false 19 | } else { 20 | return true 21 | } 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Check List 2 | 3 | Thanks for considering to open an issue. Before you submit your issue, please confirm these boxes are checked. 4 | 5 | - [ ] I have read the [README.md](https://github.com/enums/Calatrava/blob/master/README.md), but there is no information I need. 6 | - [ ] I have searched in [existing issues](https://github.com/enums/Calatrava/issues?utf8=%E2%9C%93&q=is%3Aissue), but did find a same one. 7 | 8 | ### Issue Description 9 | 10 | #### Description 11 | 12 | [Tell us about the issue] 13 | 14 | #### Reproduce 15 | 16 | [The steps to reproduce this issue. What are the parameters, where did you put your code, etc.] 17 | 18 | #### Other Comment 19 | 20 | [Add anything else here] 21 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Posts/PostsHistoryModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostsHistoryModel.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/25. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class PostsHistoryModel: PCModel { 13 | 14 | override var tableName: String { 15 | return "PostsHistory" 16 | } 17 | 18 | var date = PCDataBaseField.init(name: "DATE", type: .string, length: 10) 19 | var content = PCDataBaseField.init(name: "CONTENT", type: .string, length: 64) 20 | 21 | override func registerFields() -> [PCDataBaseField] { 22 | return [ 23 | date, content 24 | ] 25 | } 26 | 27 | override class var cacheTime: TimeInterval? { 28 | return 60 29 | } 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Source/Calatrava/Error/ErrorNotSupportView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorNotSupportView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/7/1. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class ErrorNotSupportView: PCDetailView { 13 | 14 | override var templateName: String? { 15 | return "error_notsupport.html" 16 | } 17 | 18 | override var viewParam: PCViewParam? { 19 | return [ 20 | "_pjango_template_navigation_bar": NavigationBarView.html, 21 | "_pjango_template_footer_bar": FooterBarView.html, 22 | "_pjango_param_title_message": ConfigModel.getValueForKey(.titleMessage) ?? "null", 23 | 24 | "_pjango_param_website_host": WEBSITE_HOST, 25 | ] 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Source/Calatrava/Plugin/ReportGeneratePlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReportGeneratePlugin.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/27. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class ReportGeneratePlugin: PCTimerPlugin { 13 | 14 | // 次日凌晨3点 15 | override var timerDelay: TimeInterval { 16 | return Date.tomorrow.timeIntervalSince1970 + 3 * 3600 - Date.init().timeIntervalSince1970 17 | } 18 | 19 | override var timerInterval: TimeInterval { 20 | return 24 * 3600 21 | } 22 | 23 | override var task: PCTask? { 24 | return { 25 | logger.info("[Report] Generating!") 26 | ReportDailyModel.generateAllReport() 27 | logger.info("[Report] Generated!") 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Source/Calatrava/Plugin/ReportUpdatePlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReportUpdatePlugin.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/25. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class ReportUpdatePlugin: PCTimerPlugin { 13 | 14 | override var timerInterval: TimeInterval { 15 | return 60 * 10 16 | } 17 | 18 | override var task: PCTask? { 19 | return { 20 | logger.info("[Report] Updating!") 21 | #if os(macOS) 22 | autoreleasepool { 23 | ReportCache.shared.updateCacheData() 24 | } 25 | #else 26 | ReportCache.shared.updateCacheData() 27 | #endif 28 | logger.info("[Report] Done!") 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Source/Calatrava/Error/ErrorNotFoundView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorNotFoundView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/24. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class ErrorNotFoundView: PCDetailView { 13 | 14 | override var templateName: String? { 15 | return "error_404.html" 16 | } 17 | 18 | let titleMessage = ConfigModel.getValueForKey(.titleMessage) ?? "null" 19 | 20 | override var viewParam: PCViewParam? { 21 | return [ 22 | "_pjango_template_navigation_bar": NavigationBarView.html, 23 | "_pjango_template_footer_bar": FooterBarView.html, 24 | "_pjango_param_title_message": titleMessage, 25 | 26 | "_pjango_param_website_host": WEBSITE_HOST, 27 | ] 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/VPSSSCURL/VPSSSCURL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VPSSSCURL.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2018/1/19. 6 | // 7 | 8 | import Foundation 9 | import Dispatch 10 | import SwiftyJSON 11 | import PerfectCURL 12 | import cURL 13 | 14 | class VPSSSCURL { 15 | 16 | static func getBytes(url: String) -> [UInt8] { 17 | 18 | let curl = CURL(url: url) 19 | curl.setOption(CURLOPT_PROXYTYPE, int: Int(CURLPROXY_SOCKS5.rawValue)) 20 | curl.setOption(CURLOPT_PROXY, s: "socks5h://127.0.0.1:1080") 21 | 22 | let (_, _, resBody) = curl.performFully() 23 | 24 | return resBody 25 | } 26 | 27 | static func toVPSSSCURL(url: String) -> String? { 28 | return "http://\(WEBSITE_HOST)/vpssscurl?url=\(url.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? "")" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "Calatrava", 8 | products: [ 9 | .executable( 10 | name: "Calatrava", 11 | targets: ["Calatrava"]), 12 | ], 13 | dependencies: [ 14 | .package(url:"https://github.com/enums/Pjango.git" , from: "2.1.0"), 15 | .package(url:"https://github.com/enums/Pjango-MySQL.git" , from: "2.1.0"), 16 | .package(url:"https://github.com/enums/Pjango-Postman.git" , from: "2.2.0"), 17 | ], 18 | targets: [ 19 | .target( 20 | name: "Calatrava", 21 | dependencies: [ 22 | "Pjango", 23 | "PjangoMySQL", 24 | "PjangoPostman", 25 | ]) 26 | ] 27 | ) 28 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Base/VerificationCode/VerificationHandle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VerificationHandle.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/12/23. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | func verificationHandle() -> PCUrlHandle { 12 | 13 | return pjangoHttpResponse { req, res in 14 | let ip = req.header(.custom(name: "watchdog_ip")) ?? req.remoteAddress.host 15 | if let lastTime = verificationLastTimeDict[ip] { 16 | guard Date.init().timeIntervalSince1970 - lastTime > 10 else { 17 | logger.info("Verification - Frequency anomaly @ \(ip)") 18 | pjangoHttpResponse("你请求得太频繁啦!")(req, res) 19 | return 20 | } 21 | } 22 | let (identifier, question) = VerificationManager.generateCode() 23 | pjangoHttpResponse("\(question)@\(identifier)")(req, res) 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Search/SearchView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2019/2/23. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | class SearchView: PCDetailView { 12 | 13 | override var templateName: String? { 14 | return "search.html" 15 | } 16 | 17 | override var viewParam: PCViewParam? { 18 | 19 | let titleMessage = ConfigModel.getValueForKey(.titleMessage) ?? "null" 20 | let allTags = (ModuleModel.queryObjects() as? [ModuleModel])?.filter { $0.searchable.intValue > 0 }.map { $0.toViewParam() } ?? [] 21 | 22 | return [ 23 | "_pjango_template_navigation_bar": NavigationBarView.html, 24 | "_pjango_template_footer_bar": FooterBarView.html, 25 | "_pjango_param_title_message": titleMessage, 26 | 27 | "_pjango_param_all_tags": allTags, 28 | 29 | "_pjango_param_host": WEBSITE_HOST, 30 | ] 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Update/UpdatePostsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpdatePostsView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/24. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class UpdatePostsView: PCDetailView { 13 | 14 | var model: PostsModel 15 | 16 | init(model: PostsModel) { 17 | self.model = model 18 | } 19 | 20 | required init() { 21 | fatalError("init() has not been implemented") 22 | } 23 | 24 | override var templateName: String? { 25 | return "update_posts_cell.html" 26 | } 27 | 28 | override var viewParam: PCViewParam? { 29 | return [ 30 | "_pjango_param_title": model.title.strValue, 31 | "_pjango_param_pid": model.pid.intValue, 32 | "_pjango_param_date": model.date.strValue, 33 | "_pjango_param_table_tag": model.tagModel.map { $0.toViewParam() }, 34 | 35 | "_pjango_url_host": WEBSITE_HOST 36 | ] 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Search/SearchResultPostsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchResultPostsView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2019/2/23. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | class SearchResultPostsView: PCDetailView { 12 | 13 | var model: PostsModel? 14 | 15 | init(model: PostsModel) { 16 | self.model = model 17 | } 18 | 19 | required init() { 20 | 21 | } 22 | 23 | override var templateName: String? { 24 | return "search_result_posts_cell.html" 25 | } 26 | 27 | override var viewParam: PCViewParam? { 28 | guard let model = model else { 29 | return nil 30 | } 31 | return [ 32 | "_pjango_param_title": model.title.strValue, 33 | "_pjango_param_pid": model.pid.intValue, 34 | "_pjango_param_date": model.date.strValue, 35 | "_pjango_param_table_tag": model.tagModel.map { $0.toViewParam() }, 36 | 37 | "_pjango_url_host": WEBSITE_HOST, 38 | ] 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Source/Calatrava/Plugin/DailyCleanPlugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomerCleanerPlugin.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/25. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class DailyCleanPlugin: PCTimerPlugin { 13 | 14 | override var timerDelay: TimeInterval { 15 | return Date.tomorrow.timeIntervalSince1970 - Date.init().timeIntervalSince1970 16 | } 17 | 18 | override var timerInterval: TimeInterval { 19 | return 3600 * 24 20 | } 21 | 22 | override var task: PCTask? { 23 | return { 24 | postsLoveDict.removeAll() 25 | postsCommentLastTimeDict.removeAll() 26 | postsCommentDailyDict.removeAll() 27 | corpusPostsLoveDict.removeAll() 28 | corpusPostsCommentLastTimeDict.removeAll() 29 | corpusPostsCommentDailyDict.removeAll() 30 | messageLastTimeDict.removeAll() 31 | messageDailyDict.removeAll() 32 | verificationLastTimeDict.removeAll() 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Posts/PostsSearchView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostsSearchView.swift 3 | // Pjango-Dev 4 | // 5 | // Created by 郑宇琦 on 2017/6/27. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class PostsSearchView: PCDetailView { 13 | 14 | override var templateName: String? { 15 | return "posts_search.html" 16 | } 17 | 18 | override var viewParam: PCViewParam? { 19 | 20 | let titleMessage = ConfigModel.getValueForKey(.titleMessage) ?? "null" 21 | let allTags = PostsTagModel.queryObjects()?.map { $0.toViewParam() } ?? [] 22 | 23 | return [ 24 | "_pjango_template_navigation_bar": NavigationBarView.html, 25 | "_pjango_template_footer_bar": FooterBarView.html, 26 | "_pjango_param_title_message": titleMessage, 27 | 28 | "_pjango_param_all_tags": allTags, 29 | "_pjango_url_search": pjangoUrlReverse(host: WEBSITE_HOST, name: "search") ?? "", 30 | 31 | "_pjango_param_host": WEBSITE_HOST, 32 | ] 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Update/UpdateProjectView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpdateProjectView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2017/6/24. 6 | // Copyright © 2017年 郑宇琦. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Pjango 11 | 12 | class UpdateProjectView: PCDetailView { 13 | 14 | var model: ProjectModel 15 | 16 | init(model: ProjectModel) { 17 | self.model = model 18 | } 19 | 20 | required init() { 21 | fatalError("init() has not been implemented") 22 | } 23 | 24 | override var templateName: String? { 25 | return "update_project_cell.html" 26 | } 27 | 28 | override var viewParam: PCViewParam? { 29 | return [ 30 | "_pjango_param_title": model.title.strValue, 31 | "_pjango_param_sub_title": model.subtitle.strValue, 32 | "_pjango_param_memo": model.memo.strValue, 33 | "_pjango_param_url": model.url.strValue, 34 | "_pjango_param_date": model.date.strValue, 35 | "_pjango_param_table_TAGHTML": model.tagModel.map { $0.toViewParam() } 36 | ] 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/About/MessageModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageModel.swift 3 | // Calatrava-Blog 4 | // 5 | // Created by 郑宇琦 on 2017/12/21. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | class MessageModel: PCModel { 12 | 13 | override var tableName: String { 14 | return "Message" 15 | } 16 | 17 | var mid = PCDataBaseField.init(name: "MID", type: .string, length: 128) 18 | var floor = PCDataBaseField.init(name: "FLOOR", type: .int) 19 | var admin = PCDataBaseField.init(name: "ADMIN", type: .int) 20 | var date = PCDataBaseField.init(name: "DATE", type: .string, length: 20) 21 | var name = PCDataBaseField.init(name: "NAME", type: .string, length: 64) 22 | var email = PCDataBaseField.init(name: "EMAIL", type: .string, length: 64) 23 | var comment = PCDataBaseField.init(name: "COMMENT", type: .string, length: 2048) 24 | var fromIp = PCDataBaseField.init(name: "FROM_IP", type: .string, length: 16) 25 | 26 | override func registerFields() -> [PCDataBaseField] { 27 | return [ 28 | mid, floor, admin, date, name, email, comment, fromIp 29 | ] 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Source/Calatrava/Modules/Search/SearchResultProjectView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchResultProjectView.swift 3 | // Calatrava 4 | // 5 | // Created by 郑宇琦 on 2019/2/24. 6 | // 7 | 8 | import Foundation 9 | import Pjango 10 | 11 | class SearchResultProjectView: PCDetailView { 12 | 13 | var model: ProjectModel? 14 | 15 | init(model: ProjectModel) { 16 | self.model = model 17 | } 18 | 19 | required init() { 20 | 21 | } 22 | 23 | override var templateName: String? { 24 | return "search_result_project_cell.html" 25 | } 26 | 27 | override var viewParam: PCViewParam? { 28 | guard let model = model else { 29 | return nil 30 | } 31 | return [ 32 | "_pjango_param_title": model.title.strValue, 33 | "_pjango_param_subtitle": model.subtitle.strValue, 34 | "_pjango_param_memo": model.memo.strValue, 35 | "_pjango_param_url": model.url.strValue, 36 | "_pjango_param_date": model.date.strValue, 37 | "_pjango_param_table_TAGHTML": model.tagModel.map { $0.toViewParam() } 38 | ] 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Workspace/templates/search_result_posts_cell.html: -------------------------------------------------------------------------------- 1 |
5 |
6 | 我 发表的【技术博文】:
7 |
13 | {{#_pjango_param_table_tag}} 14 | {{{_pjango_param_table_PostsTag_TAG}}} 15 | {{/_pjango_param_table_tag}} 16 |
17 | 18 |
5 |
6 | 我 发表的【文集文章】:
7 |
10 | 11 | 12 | {{_pjango_param_title}} 13 | 14 |
15 |16 | 17 | 18 | 收录于文集:《{{_pjango_param_corpus_title}}》 19 | 20 |
21 | 22 |
7 |
8 | 我 发布的【业余项目】:
9 |
{{_pjango_param_title}}
11 |{{_pjango_param_subtitle}}
12 |13 | {{#_pjango_param_table_TAGHTML}} 14 | {{{_pjango_param_table_PostsTag_TAG}}} 15 | {{/_pjango_param_table_TAGHTML}} 16 |
17 |{{_pjango_param_memo}}
18 |
5 |
6 |
7 | 我
8 | 刚刚发布了新的
9 | 文集文章:
10 |
11 |
14 | 15 | 16 | {{_pjango_param_title}} 17 | 18 |
19 |20 | 21 | 22 | 收录于文集:《{{_pjango_param_corpus_title}}》 23 | 24 |
25 | 26 |
5 |
6 |
7 | 我
8 | 刚刚发布了新
9 | 技术博文:
10 |
11 |
14 | 15 | 16 | {{_pjango_param_title}} 17 | 18 |
19 |20 | {{#_pjango_param_table_tag}} 21 | {{{_pjango_param_table_PostsTag_TAG}}} 22 | {{/_pjango_param_table_tag}} 23 |
24 | 25 |
5 |
6 |
7 | 我
8 | 刚刚发布了新的
9 | 业余项目:
10 |
11 |
14 | 15 | 16 | {{_pjango_param_title}} 17 | 18 |
19 |{{_pjango_param_sub_title}}
20 |21 | {{#_pjango_param_table_TAGHTML}} 22 | {{{_pjango_param_table_PostsTag_TAG}}} 23 | {{/_pjango_param_table_TAGHTML}} 24 |
25 |{{_pjango_param_memo}}
26 | 27 | 28 |
5 |
6 | Postman 抓取到的【Instagram】:
7 |
16 |
17 | {{_pjango_param_author_fullname}}
18 |
20 | {{_pjango_param_caption}} 21 |
22 |
5 |
6 |
7 | Postman
8 | 刚刚抓取到了的新
9 | Instagram:
10 |
11 |
20 |
21 | {{_pjango_param_author_fullname}}
22 |
24 | {{_pjango_param_caption}} 25 |
26 |
5 |
6 | 我 发布的【原创视频】:
7 |
10 | 11 | 12 | {{_pjango_param_title}} 13 | 14 |
15 |16 | 17 | 18 | 收录于播单:《{{_pjango_param_list_title}}》 19 | 20 |
21 | 22 |
29 |
30 | {{_pjango_param_name}}
31 |
33 | {{_pjango_param_memo}} 34 |
35 |
5 |
6 |
7 | 我
8 | 刚刚发布了新的
9 | 原创视频:
10 |
11 |
14 | 15 | 16 | {{_pjango_param_title}} 17 | 18 |
19 |20 | 21 | 22 | 收录于播单:《{{_pjango_param_list_title}}》 23 | 24 |
25 | 26 |
33 |
34 | {{_pjango_param_name}}
35 |
37 | {{_pjango_param_memo}} 38 |
39 |搜索全站内容
51 |60 | 全站内容 61 | {{#_pjango_param_all_tags}} 62 | {{{_pjango_param_table_Module_ICON}}} {{{_pjango_param_table_Module_TITLE}}} 63 | {{/_pjango_param_all_tags}} 64 |
65 | 66 |技术博文归档
79 |搜索全部博文
50 |60 | 全部 61 | {{#_pjango_param_all_tags}} 62 | {{{_pjango_param_table_PostsTag_TAG}}} 63 | {{/_pjango_param_all_tags}} 64 |
65 | 66 |所有内容
83 |{{{_pjango_param_table_Module_ICON}}} {{_pjango_param_table_Module_TITLE}}
97 |{{_pjango_param_table_Module_MEMO}}
98 |我的文集列表
83 |{{_pjango_param_table_Corpus_TITLE}}
93 |{{_pjango_param_table_Corpus_MEMO}}
94 |