├── .gitignore
├── LICENSE
├── README.md
└── src
├── Blog.cs
├── BubbleChars.cs
├── Cow.cs
├── Directory.Build.props
├── Program.cs
├── SayBubbleChars.cs
├── SpeechBubble.cs
├── SpinnerEx.cs
└── dotnetcowsay.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | .build
28 | # Visual Studio 2015/2017 cache/options directory
29 | .vs/
30 | .vscode/
31 | # Uncomment if you have tasks that create the project's static files in wwwroot
32 | #wwwroot/
33 | src/.vscode/
34 | # Visual Studio 2017 auto generated files
35 | Generated\ Files/
36 |
37 | # MSTest test Results
38 | [Tt]est[Rr]esult*/
39 | [Bb]uild[Ll]og.*
40 |
41 | # NUNIT
42 | *.VisualState.xml
43 | TestResult.xml
44 |
45 | # Build Results of an ATL Project
46 | [Dd]ebugPS/
47 | [Rr]eleasePS/
48 | dlldata.c
49 |
50 | # Benchmark Results
51 | BenchmarkDotNet.Artifacts/
52 |
53 | # .NET Core
54 | project.lock.json
55 | project.fragment.lock.json
56 | artifacts/
57 | **/Properties/launchSettings.json
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_i.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *.log
83 | *.vspscc
84 | *.vssscc
85 | .builds
86 | *.pidb
87 | *.svclog
88 | *.scc
89 |
90 | # Chutzpah Test files
91 | _Chutzpah*
92 |
93 | # Visual C++ cache files
94 | ipch/
95 | *.aps
96 | *.ncb
97 | *.opendb
98 | *.opensdf
99 | *.sdf
100 | *.cachefile
101 | *.VC.db
102 | *.VC.VC.opendb
103 |
104 | # Visual Studio profiler
105 | *.psess
106 | *.vsp
107 | *.vspx
108 | *.sap
109 |
110 | # Visual Studio Trace Files
111 | *.e2e
112 |
113 | # TFS 2012 Local Workspace
114 | $tf/
115 |
116 | # Guidance Automation Toolkit
117 | *.gpState
118 |
119 | # ReSharper is a .NET coding add-in
120 | _ReSharper*/
121 | *.[Rr]e[Ss]harper
122 | *.DotSettings.user
123 |
124 | # JustCode is a .NET coding add-in
125 | .JustCode
126 |
127 | # TeamCity is a build add-in
128 | _TeamCity*
129 |
130 | # DotCover is a Code Coverage Tool
131 | *.dotCover
132 |
133 | # AxoCover is a Code Coverage Tool
134 | .axoCover/*
135 | !.axoCover/settings.json
136 |
137 | # Visual Studio code coverage results
138 | *.coverage
139 | *.coveragexml
140 |
141 | # NCrunch
142 | _NCrunch_*
143 | .*crunch*.local.xml
144 | nCrunchTemp_*
145 |
146 | # MightyMoose
147 | *.mm.*
148 | AutoTest.Net/
149 |
150 | # Web workbench (sass)
151 | .sass-cache/
152 |
153 | # Installshield output folder
154 | [Ee]xpress/
155 |
156 | # DocProject is a documentation generator add-in
157 | DocProject/buildhelp/
158 | DocProject/Help/*.HxT
159 | DocProject/Help/*.HxC
160 | DocProject/Help/*.hhc
161 | DocProject/Help/*.hhk
162 | DocProject/Help/*.hhp
163 | DocProject/Help/Html2
164 | DocProject/Help/html
165 |
166 | # Click-Once directory
167 | publish/
168 |
169 | # Publish Web Output
170 | *.[Pp]ublish.xml
171 | *.azurePubxml
172 | # Note: Comment the next line if you want to checkin your web deploy settings,
173 | # but database connection strings (with potential passwords) will be unencrypted
174 | *.pubxml
175 | *.publishproj
176 |
177 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
178 | # checkin your Azure Web App publish settings, but sensitive information contained
179 | # in these scripts will be unencrypted
180 | PublishScripts/
181 |
182 | # NuGet Packages
183 | *.nupkg
184 | # The packages folder can be ignored because of Package Restore
185 | **/[Pp]ackages/*
186 | # except build/, which is used as an MSBuild target.
187 | !**/[Pp]ackages/build/
188 | # Uncomment if necessary however generally it will be regenerated when needed
189 | #!**/[Pp]ackages/repositories.config
190 | # NuGet v3's project.json files produces more ignorable files
191 | *.nuget.props
192 | *.nuget.targets
193 |
194 | # Microsoft Azure Build Output
195 | csx/
196 | *.build.csdef
197 |
198 | # Microsoft Azure Emulator
199 | ecf/
200 | rcf/
201 |
202 | # Windows Store app package directories and files
203 | AppPackages/
204 | BundleArtifacts/
205 | Package.StoreAssociation.xml
206 | _pkginfo.txt
207 | *.appx
208 |
209 | # Visual Studio cache files
210 | # files ending in .cache can be ignored
211 | *.[Cc]ache
212 | # but keep track of directories ending in .cache
213 | !*.[Cc]ache/
214 |
215 | # Others
216 | ClientBin/
217 | ~$*
218 | *~
219 | *.dbmdl
220 | *.dbproj.schemaview
221 | *.jfm
222 | *.pfx
223 | *.publishsettings
224 | orleans.codegen.cs
225 |
226 | # Including strong name files can present a security risk
227 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
228 | #*.snk
229 |
230 | # Since there are multiple workflows, uncomment next line to ignore bower_components
231 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
232 | #bower_components/
233 |
234 | # RIA/Silverlight projects
235 | Generated_Code/
236 |
237 | # Backup & report files from converting an old project file
238 | # to a newer Visual Studio version. Backup files are not needed,
239 | # because we have git ;-)
240 | _UpgradeReport_Files/
241 | Backup*/
242 | UpgradeLog*.XML
243 | UpgradeLog*.htm
244 | ServiceFabricBackup/
245 | *.rptproj.bak
246 |
247 | # SQL Server files
248 | *.mdf
249 | *.ldf
250 | *.ndf
251 |
252 | # Business Intelligence projects
253 | *.rdl.data
254 | *.bim.layout
255 | *.bim_*.settings
256 | *.rptproj.rsuser
257 |
258 | # Microsoft Fakes
259 | FakesAssemblies/
260 |
261 | # GhostDoc plugin setting file
262 | *.GhostDoc.xml
263 |
264 | # Node.js Tools for Visual Studio
265 | .ntvs_analysis.dat
266 | node_modules/
267 |
268 | # Visual Studio 6 build log
269 | *.plg
270 |
271 | # Visual Studio 6 workspace options file
272 | *.opt
273 |
274 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
275 | *.vbw
276 |
277 | # Visual Studio LightSwitch build output
278 | **/*.HTMLClient/GeneratedArtifacts
279 | **/*.DesktopClient/GeneratedArtifacts
280 | **/*.DesktopClient/ModelManifest.xml
281 | **/*.Server/GeneratedArtifacts
282 | **/*.Server/ModelManifest.xml
283 | _Pvt_Extensions
284 |
285 | # Paket dependency manager
286 | .paket/paket.exe
287 | paket-files/
288 |
289 | # FAKE - F# Make
290 | .fake/
291 |
292 | # JetBrains Rider
293 | .idea/
294 | *.sln.iml
295 |
296 | # CodeRush
297 | .cr/
298 |
299 | # Python Tools for Visual Studio (PTVS)
300 | __pycache__/
301 | *.pyc
302 |
303 | # Cake - Uncomment if you are using it
304 | # tools/**
305 | # !tools/packages.config
306 |
307 | # Tabs Studio
308 | *.tss
309 |
310 | # Telerik's JustMock configuration file
311 | *.jmconfig
312 |
313 | # BizTalk build output
314 | *.btp.cs
315 | *.btm.cs
316 | *.odx.cs
317 | *.xsd.cs
318 |
319 | # OpenCover UI analysis results
320 | OpenCover/
321 |
322 | # Azure Stream Analytics local run output
323 | ASALocalRun/
324 |
325 | # MSBuild Binary and Structured Log
326 | *.binlog
327 |
328 | # NVidia Nsight GPU debugger configuration file
329 | *.nvuser
330 |
331 | # MFractors (Xamarin productivity tool) working folder
332 | .mfractor/
333 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Isaac Levin
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 | # dotnet-cowsay
2 | .NET Core Global Tool that gives a a random blog post from discoverdot.net
3 |
4 | ## Installation
5 |
6 | ```bash
7 | dotnet tool install -g dotnet-cowsay
8 | ```
9 |
10 | ## Usage
11 |
12 | ```bash
13 | docs
14 | Usage: dotnet cowsay [arguments] [options]
15 |
16 | Arguments:
17 | Terms
18 |
19 | Options:
20 | -?|-h|--help Show help information
21 | ```
22 |
23 | ## Run
24 |
25 | ```bash
26 | dotnet cowsay
27 |
28 | __________________
29 | / Blog Title \
30 | | Article Title |
31 | \ Blog Url /
32 | -----------------
33 |
34 | \ ^__^
35 | \ (oo)\_______
36 | (__)\ )\/\
37 | ||----w |
38 | || ||
39 |
40 |
41 | ```
42 | Credit to @terrytrent for creating CowsaySharp where I took some of the Cowsay code
43 | https://github.com/terrytrent/CowsaySharp
44 |
--------------------------------------------------------------------------------
/src/Blog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace dotnetcowsay
6 | {
7 |
8 |
9 | public class Blog
10 | {
11 | public string key { get; set; }
12 | public string title { get; set; }
13 | public string link { get; set; }
14 | public string description { get; set; }
15 | public string website { get; set; }
16 | public string feed { get; set; }
17 | public string language { get; set; }
18 | public DateTime lastPublished { get; set; }
19 | public Newestfeeditem newestFeedItem { get; set; }
20 | }
21 |
22 | public class Newestfeeditem
23 | {
24 | public string title { get; set; }
25 | public string link { get; set; }
26 | public string description { get; set; }
27 | public DateTime published { get; set; }
28 | public bool recent { get; set; }
29 | public Links links { get; set; }
30 | public object author { get; set; }
31 | }
32 |
33 | public class Links
34 | {
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/BubbleChars.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace dotnetcowsay
6 | {
7 | public interface IBubbleChars
8 | {
9 | char TopLine { get; }
10 | char BottomLine { get; }
11 | string UpLeft { get; }
12 | string UpRight { get; }
13 | string DownLeft { get; }
14 | string DownRight { get; }
15 | string Left { get; }
16 | string Right { get; }
17 | string SmallLeft { get; }
18 | string SmallRight { get; }
19 | string Bubble { get; }
20 | }
21 |
22 | public class BubbleChars : IBubbleChars
23 | {
24 | public char TopLine { get; set; }
25 | public char BottomLine { get; set; }
26 | public string UpLeft { get; set; }
27 | public string UpRight { get; set; }
28 | public string DownLeft { get; set; }
29 | public string DownRight { get; set; }
30 | public string Left { get; set; }
31 | public string Right { get; set; }
32 | public string SmallLeft { get; set; }
33 | public string SmallRight { get; set; }
34 | public string Bubble { get; set; }
35 |
36 | public BubbleChars()
37 | {
38 | TopLine = '_';
39 | BottomLine = '-';
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Cow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace dotnetcowsay
6 | {
7 | public static class Cow
8 | {
9 | public static string GetCow()
10 | {
11 | var cow = @" \ ^__^
12 | \ (oo)\_______
13 | (__)\ )\/\
14 | ||----w |
15 | || ||
16 | ";
17 | return cow;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dotnet cowsay
5 | Isaac Levin
6 | dotnet-cowsay
7 | Copyright © Isaac Levin
8 | en-US
9 | false
10 | https://opensource.org/licenses/MIT
11 | https://github.com/isaac2004/dotnet-cowsay
12 | https://github.com/isaac2004/dotnet-cowsay.git
13 | git
14 | false
15 | true
16 | Latest
17 | en
18 |
19 | true
20 | true
21 |
22 | $(MSBuildThisFileDirectory).build\obj\$(MSBuildProjectName)
23 | $(MSBuildThisFileDirectory).build\bin\$(MSBuildProjectName)
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 | using McMaster.Extensions.CommandLineUtils;
4 | using System.Collections.Generic;
5 | using System.Net.Http;
6 | using Newtonsoft.Json;
7 | using Kurukuru;
8 | using System.Threading.Tasks;
9 |
10 | namespace dotnetcowsay
11 | {
12 | [Command(Description = "Cowsay a Blog Post.")]
13 | class Program
14 | {
15 | public static int Main(string[] args) => CommandLineApplication.Execute(args);
16 |
17 | private async Task OnExecute()
18 | {
19 | await GetLink();
20 |
21 | return 0;
22 | }
23 |
24 | private async Task GetLink()
25 | {
26 | await SpinnerEx.StartAsync("Looking for an awesome article..", async spinner =>
27 | {
28 | try
29 | {
30 | Blog blog = new Blog();
31 |
32 | HttpClient client = new HttpClient();
33 | string url = "https://discoverdot.net/data/blogs.json";
34 | string content = await client.GetStringAsync(url);
35 |
36 | var blogList = JsonConvert.DeserializeObject>(content);
37 | Random rnd = new Random();
38 | blog = blogList[rnd.Next(0, blogList.Count - 1)];
39 |
40 | var cow = Cow.GetCow();
41 | var bubbleText = blog.title + Environment.NewLine + blog.newestFeedItem.title + Environment.NewLine + blog.newestFeedItem.link;
42 | string SpeechBubbleReturned = SpeechBubble.ReturnSpeechBubble(bubbleText, new SayBubbleChars(), blog.newestFeedItem.link.Length);
43 | Console.WriteLine(Environment.NewLine + SpeechBubbleReturned + Environment.NewLine + cow);
44 | }
45 | catch
46 | {
47 | spinner.Fail("Something went wrong, please try again");
48 | }
49 | });
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/SayBubbleChars.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace dotnetcowsay
6 | {
7 | public class SayBubbleChars : BubbleChars
8 | {
9 | public SayBubbleChars()
10 | {
11 | UpLeft = DownRight = "/";
12 | UpRight = DownLeft = Bubble = "\\";
13 | Left = Right = "|";
14 | SmallLeft = "<";
15 | SmallRight = ">";
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/SpeechBubble.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace dotnetcowsay
7 | {
8 | static public class SpeechBubble
9 | {
10 | static public string ReturnSpeechBubble(string message, IBubbleChars bubbles, int maxLineLength)
11 | {
12 | char[] splitChar = { ' ', (char)10, (char)13 };
13 | List messageAsList = new List();
14 |
15 | messageAsList = message.Split(
16 | new[] { "\r\n", "\r", "\n" },
17 | StringSplitOptions.None
18 | ).ToList();
19 |
20 |
21 | if (message.Length > maxLineLength || messageAsList.Count > 1)
22 | {
23 | message = CreateLargeWordBubble(messageAsList, bubbles);
24 | }
25 | else
26 | {
27 | message = CreateSmallWordBubble(message, bubbles);
28 | }
29 |
30 | return message;
31 | }
32 |
33 | static string RepeatCharacter(char character, int numberOfUnderscores)
34 | {
35 | return new string(character, numberOfUnderscores);
36 | }
37 |
38 | static string CreateSmallWordBubble(string message, IBubbleChars bubbles)
39 | {
40 | int lengthOfMessage = message.Length;
41 | int lengthOfTopAndBottomLinesInBubble = lengthOfMessage + 2;
42 | string topBubbleLine = RepeatCharacter(bubbles.TopLine, lengthOfTopAndBottomLinesInBubble);
43 | string bottomBubbleLine = RepeatCharacter(bubbles.BottomLine, lengthOfTopAndBottomLinesInBubble);
44 |
45 | return $" {topBubbleLine} \r\n{bubbles.SmallLeft} {message.Trim()} {bubbles.SmallRight}\r\n {bottomBubbleLine}";
46 | }
47 |
48 | static string CreateLargeWordBubble(List list, IBubbleChars bubbles)
49 | {
50 | StringBuilder bubbleBuilder = new StringBuilder();
51 | int longestLineInList = list.Max(s => s.Length);
52 | int lengthOfTopAndBottomLinesInBubble = longestLineInList + 2;
53 | string topBubbleLine = $" {RepeatCharacter(bubbles.TopLine, lengthOfTopAndBottomLinesInBubble)}";
54 | string bottomBubbleLine = $" {RepeatCharacter(bubbles.BottomLine, lengthOfTopAndBottomLinesInBubble)}";
55 | string firstLineInMessageSpaces = RepeatCharacter(' ', longestLineInList - list[0].Length + 1);
56 | string lastLineInMessageSpaces = RepeatCharacter(' ', longestLineInList - list[list.Count - 1].Length + 1);
57 |
58 | bubbleBuilder.AppendLine(topBubbleLine);
59 | bubbleBuilder.AppendLine($"{bubbles.UpLeft} {list[0]}{firstLineInMessageSpaces}{bubbles.UpRight}");
60 | for (int i = 1; i < list.Count() - 1; i++)
61 | {
62 | int numberofspaces = longestLineInList - list[i].Length;
63 | string spacesInLine = RepeatCharacter(' ', numberofspaces + 1);
64 |
65 | bubbleBuilder.AppendLine($"{bubbles.Left} {list[i]}{spacesInLine}{bubbles.Right}");
66 | }
67 | bubbleBuilder.AppendLine($"{bubbles.DownLeft} {list[list.Count - 1]}{lastLineInMessageSpaces}{bubbles.DownRight}");
68 | bubbleBuilder.AppendLine(bottomBubbleLine);
69 |
70 | return bubbleBuilder.ToString();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/SpinnerEx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Kurukuru;
4 | using System.Threading.Tasks;
5 | namespace dotnetcowsay
6 | {
7 | static class SpinnerEx
8 | {
9 | public static void Start(string text, Action action, Pattern pattern = null, Pattern fallbackPattern = null)
10 | {
11 | Start(text, _ => action(), pattern, fallbackPattern);
12 | }
13 |
14 | public static void Start(string text, Action action, Pattern pattern = null, Pattern fallbackPattern = null)
15 | {
16 | using (var spinner = new Spinner(text, pattern, fallbackPattern: fallbackPattern))
17 | {
18 | spinner.Start();
19 |
20 | try
21 | {
22 | action(spinner);
23 |
24 | if (!spinner.Stopped)
25 | {
26 | spinner.Stop("", "");
27 | }
28 | }
29 | catch
30 | {
31 | if (!spinner.Stopped)
32 | {
33 | spinner.Stop("", "");
34 | }
35 | throw;
36 | }
37 | }
38 | }
39 |
40 | public static Task StartAsync(string text, Func action, Pattern pattern = null, Pattern fallbackPattern = null)
41 | {
42 | return StartAsync(text, _ => action(), pattern, fallbackPattern);
43 | }
44 |
45 | public static async Task StartAsync(string text, Func action, Pattern pattern = null, Pattern fallbackPattern = null)
46 | {
47 | using (var spinner = new Spinner(text, pattern, fallbackPattern: fallbackPattern))
48 | {
49 | spinner.Start();
50 |
51 | try
52 | {
53 | await action(spinner);
54 | if (!spinner.Stopped)
55 | {
56 | spinner.Stop("", "");
57 | }
58 | }
59 | catch
60 | {
61 | if (!spinner.Stopped)
62 | {
63 | spinner.Stop("", "");
64 | }
65 | throw;
66 | }
67 | }
68 | }
69 | }}
--------------------------------------------------------------------------------
/src/dotnetcowsay.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dotnet-cowsay
5 | True
6 | true
7 | Exe
8 | netcoreapp2.1
9 | dotnet-cowsay
10 | dotnetcowsay
11 | 1.0.0
12 | .NET Core Global Tool that gives a a random blog post from discoverdot.net
13 | dotnet, global tools, cowsay
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------