Adding the initial code
This commit is contained in:
parent
b7f24eac37
commit
3e560032e4
2 changed files with 373 additions and 0 deletions
25
LICENSE
Normal file
25
LICENSE
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
BSD 2-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2020, Elia el Lazkani
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
348
main.go
Normal file
348
main.go
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
flag "github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create a list of constants to figure out
|
||||||
|
// the command line flags and translate them
|
||||||
|
// into uri flags.
|
||||||
|
const (
|
||||||
|
METRIC = 1 << iota
|
||||||
|
USCS
|
||||||
|
METERSECOND
|
||||||
|
ZERO
|
||||||
|
ONE
|
||||||
|
TWO
|
||||||
|
IGNOREUSERAGENT
|
||||||
|
FOLLOWLINK
|
||||||
|
NARROW
|
||||||
|
QUIET
|
||||||
|
SUPERQUIET
|
||||||
|
NOCOLORS
|
||||||
|
ADDFRAME
|
||||||
|
MIDTRANSPARENCY
|
||||||
|
TRANSPARENCY
|
||||||
|
LOCATION
|
||||||
|
LANGUAGE
|
||||||
|
PNG
|
||||||
|
VTWO
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create a list of constants to define
|
||||||
|
// uri switches by flag.
|
||||||
|
const (
|
||||||
|
MetricSwitch = "m"
|
||||||
|
UscsSwitch = "u"
|
||||||
|
MeterSecondSwitch = "M"
|
||||||
|
ZeroSwitch = "0"
|
||||||
|
OneSwitch = "1"
|
||||||
|
TwoSwitch = "2"
|
||||||
|
IgnoreUserAgentSwitch = "A"
|
||||||
|
FollowLinkSwitch = "F"
|
||||||
|
NarrowSwitch = "n"
|
||||||
|
QuietSwitch = "q"
|
||||||
|
SuperQuietSwitch = "Q"
|
||||||
|
NoColorsSwitch = "T"
|
||||||
|
AddFrameSwitch = "p"
|
||||||
|
MidTransparencySwitch = "T"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Define a command parameters struct.
|
||||||
|
// This will hold all the configurations
|
||||||
|
// set by the command line parameters provided.
|
||||||
|
type cmdParams struct {
|
||||||
|
Flags int
|
||||||
|
TransparencyLevel int
|
||||||
|
Location string
|
||||||
|
Language string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a method to figure out the command parameters
|
||||||
|
// provided and translate them into uri parameters.
|
||||||
|
// This will figure out if we need to download the PNG image
|
||||||
|
// as well.
|
||||||
|
func (cmdP *cmdParams) generateParamFormat() (string, bool, error) {
|
||||||
|
var params []string
|
||||||
|
var prefix []string
|
||||||
|
var download bool
|
||||||
|
prefix = append(prefix, "?")
|
||||||
|
|
||||||
|
if cmdP.Flags&METRIC == METRIC {
|
||||||
|
params = append(params, MetricSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&USCS == USCS {
|
||||||
|
params = append(params, UscsSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&METERSECOND == METERSECOND {
|
||||||
|
params = append(params, MeterSecondSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&ZERO == ZERO {
|
||||||
|
params = append(params, ZeroSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&ONE == ONE {
|
||||||
|
params = append(params, OneSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&TWO == TWO {
|
||||||
|
params = append(params, TwoSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&IGNOREUSERAGENT == IGNOREUSERAGENT {
|
||||||
|
params = append(params, IgnoreUserAgentSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&FOLLOWLINK == FOLLOWLINK {
|
||||||
|
params = append(params, FollowLinkSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&NARROW == NARROW {
|
||||||
|
params = append(params, NarrowSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&QUIET == QUIET {
|
||||||
|
params = append(params, QuietSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&SUPERQUIET == SUPERQUIET {
|
||||||
|
params = append(params, SuperQuietSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&NOCOLORS == NOCOLORS {
|
||||||
|
params = append(params, NoColorsSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&ADDFRAME == ADDFRAME {
|
||||||
|
params = append(params, AddFrameSwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&MIDTRANSPARENCY == MIDTRANSPARENCY {
|
||||||
|
params = append(params, MidTransparencySwitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdP.Flags&PNG == PNG {
|
||||||
|
prefix[0] = "_"
|
||||||
|
|
||||||
|
if cmdP.Flags&TRANSPARENCY == TRANSPARENCY && cmdP.TransparencyLevel >= 0 && cmdP.TransparencyLevel <= 100 {
|
||||||
|
params = append(params, strings.Join([]string{"_transparency=", string(cmdP.TransparencyLevel)}, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
params = append(params, ".png")
|
||||||
|
download = true
|
||||||
|
}
|
||||||
|
|
||||||
|
params = append(prefix, strings.Join(params, ""))
|
||||||
|
|
||||||
|
return strings.Join(params, ""), download, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// * Fix the description for help
|
||||||
|
//
|
||||||
|
// Create a function to parse all the command line parameters
|
||||||
|
// provided and save them in the parameter struct.
|
||||||
|
func flagParser(cmdP *cmdParams) {
|
||||||
|
metric := flag.Bool("metric", false, "Display weather in metric")
|
||||||
|
uscs := flag.Bool("uscs", false, "Display weather Imperial")
|
||||||
|
meterSecond := flag.Bool("meter-second", false, "Display wind in m/s")
|
||||||
|
zero := flag.Bool("zero", false, "Show the weather now")
|
||||||
|
one := flag.Bool("one", false, "Show the weather for one day")
|
||||||
|
two := flag.Bool("two", false, "Show the weather for two days")
|
||||||
|
ignoreUserAgent := flag.Bool("ignore-user-agent", false, "Request ignoring the user agent")
|
||||||
|
followLink := flag.Bool("follow-link", true, "Follow link redirect")
|
||||||
|
narrow := flag.Bool("narrow", false, "Display weather in narrow view")
|
||||||
|
quiet := flag.Bool("quiet", false, "Add the quiet flag")
|
||||||
|
superQuiet := flag.Bool("super-quiet", false, "Add the super quiet flag")
|
||||||
|
noColors := flag.Bool("no-colors", false, "Disable displaying colors")
|
||||||
|
addFrame := flag.Bool("add-frame", false, "Add a frame to the output")
|
||||||
|
midTransparency := flag.Bool("mid-transparency", false, "Enable mid-transparency (PNG only)")
|
||||||
|
transparency := flag.Bool("transparency", false, "Enable transparency (PNG only)")
|
||||||
|
png := flag.Bool("png", false, "Download a weather PNG image")
|
||||||
|
v2 := flag.Bool("v2", false, "Use the v2 endpoint")
|
||||||
|
transparencyLevel := flag.Int("transparency-level", 0, "Set transparency level between 0 and 100 ")
|
||||||
|
location := flag.String("location", "", "Specify explicite location")
|
||||||
|
language := flag.String("language", "", "Speficy explicite language")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *metric {
|
||||||
|
cmdP.Flags += METRIC
|
||||||
|
}
|
||||||
|
|
||||||
|
if *uscs {
|
||||||
|
cmdP.Flags += USCS
|
||||||
|
}
|
||||||
|
|
||||||
|
if *meterSecond {
|
||||||
|
cmdP.Flags += METERSECOND
|
||||||
|
}
|
||||||
|
|
||||||
|
if *zero {
|
||||||
|
cmdP.Flags += ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
if *one {
|
||||||
|
cmdP.Flags += ONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if *two {
|
||||||
|
cmdP.Flags += TWO
|
||||||
|
}
|
||||||
|
|
||||||
|
if *ignoreUserAgent {
|
||||||
|
cmdP.Flags += IGNOREUSERAGENT
|
||||||
|
}
|
||||||
|
|
||||||
|
if *followLink {
|
||||||
|
cmdP.Flags += FOLLOWLINK
|
||||||
|
}
|
||||||
|
|
||||||
|
if *narrow {
|
||||||
|
cmdP.Flags += NARROW
|
||||||
|
}
|
||||||
|
|
||||||
|
if *quiet {
|
||||||
|
cmdP.Flags += QUIET
|
||||||
|
}
|
||||||
|
|
||||||
|
if *superQuiet {
|
||||||
|
cmdP.Flags += SUPERQUIET
|
||||||
|
}
|
||||||
|
|
||||||
|
if *noColors {
|
||||||
|
cmdP.Flags += NOCOLORS
|
||||||
|
}
|
||||||
|
|
||||||
|
if *addFrame {
|
||||||
|
cmdP.Flags += ADDFRAME
|
||||||
|
}
|
||||||
|
|
||||||
|
if *midTransparency {
|
||||||
|
cmdP.Flags += MIDTRANSPARENCY
|
||||||
|
}
|
||||||
|
|
||||||
|
if *transparency {
|
||||||
|
cmdP.Flags += TRANSPARENCY
|
||||||
|
cmdP.TransparencyLevel = *transparencyLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
if *png {
|
||||||
|
cmdP.Flags += PNG
|
||||||
|
}
|
||||||
|
|
||||||
|
if *v2 {
|
||||||
|
cmdP.Flags += VTWO
|
||||||
|
}
|
||||||
|
|
||||||
|
if *location != "" {
|
||||||
|
cmdP.Flags += LOCATION
|
||||||
|
cmdP.Location = *location
|
||||||
|
}
|
||||||
|
|
||||||
|
if *language != "" {
|
||||||
|
cmdP.Flags += LANGUAGE
|
||||||
|
cmdP.Language = *language
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a function to generate the url that we'll be calling shortly.
|
||||||
|
func generateURL(domain string, v2 bool, location string, lang string, format string) ([]string, map[string]string) {
|
||||||
|
var link []string
|
||||||
|
var headers = make(map[string]string)
|
||||||
|
|
||||||
|
link = append(link, "https://")
|
||||||
|
|
||||||
|
if v2 {
|
||||||
|
link = append(link, "v2.")
|
||||||
|
}
|
||||||
|
|
||||||
|
link = append(link, domain, "/")
|
||||||
|
|
||||||
|
if location != "" {
|
||||||
|
link = append(link, location)
|
||||||
|
}
|
||||||
|
|
||||||
|
if format != "" {
|
||||||
|
link = append(link, format)
|
||||||
|
}
|
||||||
|
|
||||||
|
if lang != "" {
|
||||||
|
headers["Accept-Language"] = lang
|
||||||
|
}
|
||||||
|
|
||||||
|
return link, headers
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// * Create interfaces to print and save and migrate code to them
|
||||||
|
//
|
||||||
|
// Figure out if we need to print or download a PNG image
|
||||||
|
// and call the server accordingly.
|
||||||
|
func getWheather(url string, headers map[string]string, download bool) {
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error reading request. ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
// I had to read the wttr.in code to figure this one out.
|
||||||
|
// It wasn't Golang, it was 2 wasted hours that I won't be getting back.
|
||||||
|
req.Header.Set("User-Agent", "curl")
|
||||||
|
|
||||||
|
for key, value := range headers {
|
||||||
|
req.Header.Add(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
client.Jar = nil
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error reading response. ", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if download {
|
||||||
|
splitURL := strings.Split(url, "/")
|
||||||
|
filename := splitURL[len(splitURL)-1]
|
||||||
|
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(f, resp.Body)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error reading body. ", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the main function that glues everything together.
|
||||||
|
func main() {
|
||||||
|
var params cmdParams = cmdParams{}
|
||||||
|
var domain string = "wttr.in"
|
||||||
|
flagParser(¶ms)
|
||||||
|
format, download, _ := params.generateParamFormat()
|
||||||
|
link, headers := generateURL(domain, params.Flags&VTWO == VTWO, params.Location, params.Language, format)
|
||||||
|
getWheather(strings.Join(link, ""), headers, download)
|
||||||
|
}
|
Loading…
Reference in a new issue