├── life
├── icon.png
├── life.png
├── life.alfredworkflow
├── Makefile
├── life.swift
└── info.plist
├── chouti
├── icon.png
├── chouti.png
├── chouti.alfredworkflow
├── Makefile
├── chouti.swift
└── info.plist
├── README.md
└── .gitignore
/life/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CFNull/workflow/HEAD/life/icon.png
--------------------------------------------------------------------------------
/life/life.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CFNull/workflow/HEAD/life/life.png
--------------------------------------------------------------------------------
/chouti/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CFNull/workflow/HEAD/chouti/icon.png
--------------------------------------------------------------------------------
/chouti/chouti.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CFNull/workflow/HEAD/chouti/chouti.png
--------------------------------------------------------------------------------
/life/life.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CFNull/workflow/HEAD/life/life.alfredworkflow
--------------------------------------------------------------------------------
/chouti/chouti.alfredworkflow:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CFNull/workflow/HEAD/chouti/chouti.alfredworkflow
--------------------------------------------------------------------------------
/life/Makefile:
--------------------------------------------------------------------------------
1 | OUTPUT = life.alfredworkflow
2 | FILES = Info.plist life.swift icon.png
3 |
4 | all: $(OUTPUT)
5 |
6 | clean:
7 | -rm $(OUTPUT)
8 |
9 | $(OUTPUT): $(FILES)
10 | zip $@ $(FILES)
11 |
--------------------------------------------------------------------------------
/chouti/Makefile:
--------------------------------------------------------------------------------
1 | OUTPUT = chouti.alfredworkflow
2 | FILES = Info.plist chouti.swift icon.png
3 |
4 | all: $(OUTPUT)
5 |
6 | clean:
7 | -rm $(OUTPUT)
8 |
9 | $(OUTPUT): $(FILES)
10 | zip $@ $(FILES)
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Workflow
2 |
3 | 用swift写下Alfred workflow
4 |
5 | ## [人生进度条](https://raw.githubusercontent.com/pdso/workflow/master/life/life.alfredworkflow)
6 |
7 | ### 输入 `life` 查看进度
8 |
9 | 
10 |
11 | ## [抽屉新热榜](https://raw.githubusercontent.com/pdso/workflow/master/chouti/chouti.alfredworkflow)
12 |
13 | ### 输入 `chouti`看新闻
14 |
15 | 
16 |
--------------------------------------------------------------------------------
/chouti/chouti.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/swift
2 | // chouti
3 | // Created by pqso on 2022/1/6.
4 | // Copyright © 2022 pqso. All rights reserved.
5 |
6 | import Foundation
7 |
8 | struct Response: Codable {
9 | let data: [Entry]
10 | }
11 |
12 | struct Entry: Codable {
13 | let title: String
14 | let originalUrl: String
15 | let sectionImgUrl: String?
16 | let sectionName: String?
17 | }
18 |
19 | let sectionName = "抽屉挂了吗"
20 |
21 | var sema = DispatchSemaphore( value: 0 )
22 |
23 | if let url = URL(string: "https://m.chouti.com/api/m/link/hot?afterTime=0") {
24 | URLSession.shared.dataTask(with: url) { data, response, error in
25 | var array: [[String : String]] = []
26 | if let data = data {
27 | let jsonDecoder = JSONDecoder()
28 | do {
29 | let res = try jsonDecoder.decode(Response.self, from: data)
30 | res.data.forEach { entry in
31 | array.append([
32 | "title": entry.title,
33 | "subtitle": entry.sectionName ?? sectionName,
34 | "arg": entry.originalUrl
35 | ])
36 | }
37 |
38 | let items = ["items": array]
39 | let resultData = try JSONSerialization.data(withJSONObject: items, options: .prettyPrinted)
40 | print(String(data: resultData, encoding: .utf8)!)
41 |
42 | }catch{
43 | let items = ["items": ["title": error.localizedDescription]]
44 | print(items)
45 | }
46 | }
47 | sema.signal()
48 | }.resume()
49 | }
50 |
51 | sema.wait()
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | # Package.resolved
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 | Carthage/Build
57 |
58 | # fastlane
59 | #
60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
61 | # screenshots whenever they are needed.
62 | # For more information about the recommended setup visit:
63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
64 |
65 | fastlane/report.xml
66 | fastlane/Preview.html
67 | fastlane/screenshots/**/*.png
68 | fastlane/test_output
69 |
--------------------------------------------------------------------------------
/life/life.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/swift
2 | // life
3 | // Created by pqso on 2019/10/9.
4 | // Copyright © 2019 pqso. All rights reserved.
5 |
6 | import Foundation
7 |
8 | func getSubTitle(_ count: Int, total: Int) -> String {
9 | let finished = "■"
10 | let unFinished = "□"
11 |
12 | let percent = Double(count) / Double(total)
13 | let f = lrint(30 * percent)
14 | let uF = 30 - f
15 |
16 | return String(repeating: finished, count: f) + String(repeating: unFinished, count: uF) + " \(lrint(percent * 100))%"
17 | }
18 |
19 | struct Life{
20 | enum Style: String{
21 | case hoursInDay = "hoursInDay"
22 | case dayInWeek = "dayInWeek"
23 | case weekInYear = "weekInYear"
24 | case dayInMonth = "dayInMonth"
25 | case monthInYear = "monthInYear"
26 | }
27 | let style: Style
28 | var alfredItem: [String: String] = [:]
29 |
30 | init(_ style: Style) {
31 | let calendar = Calendar.current
32 | let date = Date()
33 | let year = calendar.component(.year, from: date)
34 |
35 | var dic: [String : String] = [:]
36 | switch style {
37 | case .hoursInDay:
38 | let hour = calendar.component(.hour, from:date)
39 | dic = ["title": "今天已经过去了 \(hour) 小时", "subtitle": getSubTitle(hour, total: 23), "arg": "这是一个测试"]
40 | case .dayInWeek:
41 | let day = calendar.component(.weekday, from: date)
42 | dic = ["title": "本周已过去了 \(day - 1) 天", "subtitle": getSubTitle(day - 1, total: 7)]
43 | case .weekInYear:
44 | let weekRange = calendar.range(of: .weekOfYear, in: .yearForWeekOfYear, for: Date())!
45 | let week = calendar.component(.weekOfYear, from: date)
46 | dic = ["title": "\(year) 年已经过去了 \(week - 1) 周", "subtitle": getSubTitle(week - 1, total: weekRange.count)]
47 | case .dayInMonth:
48 | let dayth = calendar.component(.day, from: date)
49 | let monthRange = calendar.range(of: .day, in: .month, for: date)!
50 | dic = ["title": "这个月已经过去了 \(dayth - 1) 天", "subtitle": getSubTitle(dayth - 1, total: monthRange.count)]
51 | case .monthInYear:
52 | let month = calendar.component(.month, from: date)
53 | dic = ["title": "\(year) 年已经过去了 \(month - 1) 个月", "subtitle": getSubTitle(month - 1, total: 12)]
54 | }
55 | self.style = style
56 | dic["arg"] = dic["title"]! + "\n" + dic["subtitle"]!
57 | alfredItem = dic
58 | }
59 | }
60 |
61 | let hoursInDay = Life(.hoursInDay).alfredItem
62 | let dayInWeek = Life(.dayInWeek).alfredItem
63 | let weekInYear = Life(.weekInYear).alfredItem
64 | let dayInMonth = Life(.dayInMonth).alfredItem
65 | let monthInYear = Life(.monthInYear).alfredItem
66 |
67 | let alfredItems = ["items": [hoursInDay, dayInWeek, dayInMonth, weekInYear, monthInYear]]
68 | let resultData = try JSONSerialization.data(withJSONObject: alfredItems, options: .prettyPrinted)
69 | print(String(data: resultData, encoding: .utf8)!)
70 |
--------------------------------------------------------------------------------
/chouti/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | pq.swift.chouti
7 | connections
8 |
9 | 50B0CD10-4D52-4898-9C05-DD3A34A829C3
10 |
11 |
12 | destinationuid
13 | 33731783-BC44-4EAF-A155-F336BA94879C
14 | modifiers
15 | 0
16 | modifiersubtext
17 |
18 | vitoclose
19 |
20 |
21 |
22 |
23 | createdby
24 | pqso
25 | description
26 | 有点正经的内容社区
27 | disabled
28 |
29 | name
30 | chouti
31 | objects
32 |
33 |
34 | config
35 |
36 | browser
37 |
38 | spaces
39 |
40 | url
41 | {query}
42 | utf8
43 |
44 |
45 | type
46 | alfred.workflow.action.openurl
47 | uid
48 | 33731783-BC44-4EAF-A155-F336BA94879C
49 | version
50 | 1
51 |
52 |
53 | config
54 |
55 | alfredfiltersresults
56 |
57 | alfredfiltersresultsmatchmode
58 | 0
59 | argumenttreatemptyqueryasnil
60 |
61 | argumenttrimmode
62 | 0
63 | argumenttype
64 | 1
65 | escaping
66 | 127
67 | keyword
68 | chouti
69 | queuedelaycustom
70 | 1
71 | queuedelayimmediatelyinitially
72 |
73 | queuedelaymode
74 | 0
75 | queuemode
76 | 1
77 | runningsubtext
78 | 正在努力请求数据
79 | scriptargtype
80 | 1
81 | scriptfile
82 | chouti.swift
83 | subtext
84 | 有点正经有内容社区
85 | title
86 | 抽屉新热榜
87 | type
88 | 8
89 | withspace
90 |
91 |
92 | type
93 | alfred.workflow.input.scriptfilter
94 | uid
95 | 50B0CD10-4D52-4898-9C05-DD3A34A829C3
96 | version
97 | 3
98 |
99 |
100 | readme
101 | 抽屉新热榜
102 | uidata
103 |
104 | 33731783-BC44-4EAF-A155-F336BA94879C
105 |
106 | xpos
107 | 240
108 | ypos
109 | 50
110 |
111 | 50B0CD10-4D52-4898-9C05-DD3A34A829C3
112 |
113 | note
114 | 抽屉新热榜
115 | xpos
116 | 70
117 | ypos
118 | 50
119 |
120 |
121 | variablesdontexport
122 |
123 | version
124 | 1.0.0
125 | webaddress
126 | https://dig.chouti.com
127 |
128 |
129 |
--------------------------------------------------------------------------------
/life/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | pd.swift.life
7 | category
8 | Tools
9 | connections
10 |
11 | 50B0CD10-4D52-4898-9C05-DD3A34A829C3
12 |
13 |
14 | destinationuid
15 | 78006BFE-6A14-487D-B2FC-434544A46A7A
16 | modifiers
17 | 0
18 | modifiersubtext
19 |
20 | vitoclose
21 |
22 |
23 |
24 | 78006BFE-6A14-487D-B2FC-434544A46A7A
25 |
26 |
27 | createdby
28 | pdso
29 | description
30 | 人生进度条
31 | disabled
32 |
33 | name
34 | life progress
35 | objects
36 |
37 |
38 | config
39 |
40 | alfredfiltersresults
41 |
42 | alfredfiltersresultsmatchmode
43 | 0
44 | argumenttreatemptyqueryasnil
45 |
46 | argumenttrimmode
47 | 0
48 | argumenttype
49 | 2
50 | escaping
51 | 127
52 | keyword
53 | life
54 | queuedelaycustom
55 | 3
56 | queuedelayimmediatelyinitially
57 |
58 | queuedelaymode
59 | 0
60 | queuemode
61 | 1
62 | runningsubtext
63 |
64 | script
65 | #
66 | # Alfred Script Filter JSON format
67 | #
68 | # This example demonstrates all fields available for populating results.
69 | #
70 | # For an in-depth explanation, use the (?) help button to the bottom left.
71 | #
72 |
73 | cat << EOB
74 | {"items": [
75 |
76 | {
77 | "uid": "desktop",
78 | "type": "file",
79 | "title": "Desktop",
80 | "subtitle": "~/Desktop",
81 | "arg": "~/Desktop",
82 | "autocomplete": "Desktop",
83 | "icon": {
84 | "type": "fileicon",
85 | "path": "~/Desktop"
86 | }
87 | },
88 |
89 | {
90 | "valid": false,
91 | "uid": "flickr",
92 | "title": "Flickr",
93 | "icon": {
94 | "path": "flickr.png"
95 | }
96 | },
97 |
98 | {
99 | "uid": "image",
100 | "type": "file",
101 | "title": "My holiday photo",
102 | "subtitle": "~/Pictures/My holiday photo.jpg",
103 | "autocomplete": "My holiday photo",
104 | "icon": {
105 | "type": "filetype",
106 | "path": "public.jpeg"
107 | }
108 | },
109 |
110 | {
111 | "valid": false,
112 | "uid": "alfredapp",
113 | "title": "Alfred Website",
114 | "subtitle": "https://www.alfredapp.com/",
115 | "arg": "alfredapp.com",
116 | "autocomplete": "Alfred Website",
117 | "quicklookurl": "https://www.alfredapp.com/",
118 | "mods": {
119 | "alt": {
120 | "valid": true,
121 | "arg": "alfredapp.com/powerpack",
122 | "subtitle": "https://www.alfredapp.com/powerpack/"
123 | },
124 | "cmd": {
125 | "valid": true,
126 | "arg": "alfredapp.com/powerpack/buy/",
127 | "subtitle": "https://www.alfredapp.com/powerpack/buy/"
128 | },
129 | },
130 | "text": {
131 | "copy": "https://www.alfredapp.com/ (text here to copy)",
132 | "largetype": "https://www.alfredapp.com/ (text here for large type)"
133 | }
134 | }
135 |
136 | ]}
137 | EOB
138 | scriptargtype
139 | 1
140 | scriptfile
141 | life.swift
142 | subtext
143 |
144 | title
145 | 人生进度条
146 | type
147 | 8
148 | withspace
149 |
150 |
151 | type
152 | alfred.workflow.input.scriptfilter
153 | uid
154 | 50B0CD10-4D52-4898-9C05-DD3A34A829C3
155 | version
156 | 3
157 |
158 |
159 | config
160 |
161 | autopaste
162 |
163 | clipboardtext
164 | {query}
165 | transient
166 |
167 |
168 | type
169 | alfred.workflow.output.clipboard
170 | uid
171 | 78006BFE-6A14-487D-B2FC-434544A46A7A
172 | version
173 | 3
174 |
175 |
176 | readme
177 | 人生进度条
178 | Alfred 3 now supports JSON, which is the recommended format. XML is also supported for legacy Alfred 2 workflows, and has been updated to include the new features.
179 |
180 | A new option now exists for Script Filters, "Alfred filters results". This allows you to return a whole list of results, let Alfred do the subsequent filtering with extreme performance. When this option is selected, your script will be called once with no argument.
181 | uidata
182 |
183 | 50B0CD10-4D52-4898-9C05-DD3A34A829C3
184 |
185 | note
186 | lifeprogress
187 | xpos
188 | 70
189 | ypos
190 | 65
191 |
192 | 78006BFE-6A14-487D-B2FC-434544A46A7A
193 |
194 | xpos
195 | 240
196 | ypos
197 | 65
198 |
199 |
200 | version
201 | 1.0.0
202 | webaddress
203 | https://github.com/pdso/workflow
204 |
205 |
206 |
--------------------------------------------------------------------------------