Adding the initial code

This commit is contained in:
Elia el Lazkani 2020-02-16 21:06:37 +00:00
parent b7f24eac37
commit 3e560032e4
2 changed files with 373 additions and 0 deletions

25
LICENSE Normal file
View 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
View 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(&params)
format, download, _ := params.generateParamFormat()
link, headers := generateURL(domain, params.Flags&VTWO == VTWO, params.Location, params.Language, format)
getWheather(strings.Join(link, ""), headers, download)
}