Insert slice into url link as text - go

I am trying to make a bot which sends mails. I got the following code. I am wondering, if it's possible to place the mails slice into this field seperated by a , ?
&bcc=
If my test.txt contains
test1#mail.com
test2#mail.com
I'd like the part of the link to contain &bcc=test1#mail.com,test2#mail.com
Is this doable with Go?
package main
import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
)
func main() {
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
var mails []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
mails = append(mails, scanner.Text())
}
fmt.Println(mails)
exec.Command("xdg-open", "https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=contact#test.com,&bcc=test1#mail.com,test2#mail.com&su=Hello+World!&body=This+Is+Just+An+Example").Run()
}

You can use "fmt.Sprintf()".It solves your problem.
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
var mails []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
mails = append(mails, scanner.Text())
}
sendMails := ""
for _, m := range mails {
sendMails += fmt.Sprintf("%s", m)
}
command := fmt.Sprintf("https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=contact#test.com,&bcc=%s&su=Hello+World!&body=This+Is+Just+An+Example", sendMails)
fmt.Println(mails)
exec.Command("xdg-open", command).Run()
}

Related

How to get the output of a command

I am calling a python script from Go code:
package main
import (
"os/exec"
"os"
"fmt"
"time"
"encoding/json"
)
func main() {
cmd := exec.Command("python","/home/devendra/Desktop/sync/blur_multithread.py","http://4.imimg.com/data4/TP/ED/NSDMERP-28759633/audiovideojocks.png")
var logs=make(map[string]interface{})
logs["tes"]=os.Stdout
_ = cmd.Run()
WriteLogs(logs)//Writelog is my function which logs everything in a file
}
func WriteLogs(logs map[string]interface{}){
currentTime := time.Now().Local()
jsonLog, err := json.Marshal(logs)
if err != nil {
fmt.Println(err.Error())
}
jsonLogString := string(jsonLog[:len(jsonLog)])
logfile := "/home/devendra/ImageServiceLogs/"+ "ImageServiceLogs_" + currentTime.Format("2006-01-02") + ".txt"
if logfile == "" {
fmt.Println("Could not find logfile in configuration ...!!!")
} else {
jsonLogFile, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
defer jsonLogFile.Close()
if err != nil {
fmt.Println(err.Error())
}
jsonLogFile.WriteString(jsonLogString + "\n")
}
}
But in the logs value of tes field is null while my python script is giving me output. How to get the output of python script in my code?
As per official documentation examples, exec.Cmd.Ouput() ([]byte, error) will give you the sdout of the command after it has finished running.
https://golang.org/pkg/os/exec/#Cmd.Output
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
out, err := exec.Command("date").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
To receive both stdout and stderr of the process, writer should use exec.Cmd.CombinedOutput
https://golang.org/pkg/os/exec/#Cmd.CombinedOutput
If someone wants to receive the command output in real time to its terminal, then the writer should set exec.Cmd.Stdout and exec.Cmd.Stderr properties to, respectively, os.Stdout and os.Stderr and invoke the exec.Cmd.Run() error method.
https://golang.org/pkg/os/exec/#Cmd
https://golang.org/pkg/os/exec/#Cmd.Run
package main
import (
"fmt"
"log"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("date")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
To forward outputs and capture it at the same time, writer should seek help of the io package to use an io.MultiWriter
https://golang.org/pkg/io/#MultiWriter
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
)
func main() {
stdout := new(bytes.Bufer)
stderr := new(bytes.Bufer)
cmd := exec.Command("date")
cmd.Stdout = io.MultiWriter(os.Stdout, stdout)
cmd.Stderr = io.MultiWriter(os.Stderr, stderr)
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
Alternatively, you can make use of the exec.Cmd.{Stdout,Stderr}Pipe() see the official documentation examples https://golang.org/pkg/os/exec/#Cmd.StdoutPipe

Different result when run io.Copy(os.Stdout, &r) consecutively in Golang

I am playing around Golang. About io.Copy
I put 2 consecutive io.Copy in the code, but i expect it output twice result(testtesttest). But the 2nd one is nil. Can anyone help explain why? tks
package main
import (
"io"
"os"
"strings"
"fmt"
)
type testReader struct {
w io.Reader
str string
}
func (tt *testReader) Read (b []byte) (n int, err error) {
io.Copy(os.Stdout, tt.w)
n, err = tt.w.Read(b)
if tt.w !=nil {
return 0,io.EOF
}
return
}
func main() {
s := strings.NewReader("testtesttest!!!")
r := testReader{s,"ttthhh"}
fmt.Println(&r)
io.Copy(os.Stdout, &r)
// s.Seek(0,0) // solution from Poy's answer
io.Copy(os.Stdout, &r)
}
I'm going to prune down the given example to (as there is a bit of noise):
package main
import (
"io"
"os"
"strings"
)
func main() {
s := strings.NewReader("testtesttest")
io.Copy(os.Stdout, s) // Will print "testtesttest"
io.Copy(os.Stdout, s) // Won't print anything
}
The reason the second copy won't output anything is the io.Reader (s) has already been read. Reading from a io.Reader is not idempotent (you can't call it twice to get the same results). It also doesn't have a way to "reset" it or anything.
As #JRLambert pointed out you have s.Seek() and s.Reset() to allow you to start reading again.
Quick addition to all the correct answers (#poy and #JRLambert) provided so far... Use io.TeeReader or io.MultiWriter for times when you would want to use io.Copy more than once. Below are some examples of using each.
Using io.TeeReader
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
sourceFile, _ := os.Open("source/ebook.pdf")
var buf bytes.Buffer
tee := io.TeeReader(sourceFile, &buf)
process := func(sourceReader io.Reader) {
targetFile, _ := os.Create("target/ebook.pdf")
defer targetFile.Close()
if _, err := io.Copy(targetFile, sourceReader); err != nil {
fmt.Println(err)
}
}
process(tee)
fmt.Println(checksum(&buf))
}
func checksum(buf *bytes.Buffer) string {
h := md5.New()
b, _ := ioutil.ReadAll(buf)
if _, err := h.Write(b); err != nil {
fmt.Println(err)
}
return hex.EncodeToString(h.Sum(nil)[:16])
}
Using io.MultiWriter
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
sourceFile, _ := os.Open("source/ebook.pdf")
process := func(sourceReader io.Reader) {
targetFile, _ := os.Create("target/ebook.pdf")
defer targetFile.Close()
var buf1, buf2 bytes.Buffer
w := io.MultiWriter(targetFile, &buf1, &buf2)
if _, err := io.Copy(w, sourceReader); err != nil {
fmt.Println(err)
}
fmt.Println(checksum(&buf1))
fmt.Println(checksum(&buf2))
}
process(sourceFile)
}
func checksum(buf *bytes.Buffer) string {
h := md5.New()
b, _ := ioutil.ReadAll(buf)
if _, err := h.Write(b); err != nil {
fmt.Println(err)
}
return hex.EncodeToString(h.Sum(nil)[:16])
}

Golang find most recent file by date and time

I am not sure if I am doing this correctly, but ultimately I would like to find the most recent modified date of a file in a directory and return the file name. The code I have so far is as follows. Can someone please help me with a more efficient solution than this. I really have a feeling this is super hacky. What I am doing is getting the dates and removing the
package main
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
)
func main() {
dir := "C:\\temp\\"
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
fi, _ := os.Stat(dir + f.Name())
s := strings.Split(fi.ModTime().Format("2006-01-02 15.04.05.000"), " ")
fdate, err := strconv.Atoi(strings.Replace(s[0], "-", "", -1))
if err != nil {
fmt.Println(err)
}
ftime, err := strconv.Atoi(strings.Replace(s[1], ".", "", -1))
if err != nil {
fmt.Println(err)
}
fmt.Println(fi.Name(), fdate+ftime)
}
}
Pay attention to details and efficiency. Check for errors. You asked for files so skip directories and other things. Allow for multiple files with the same modified time stamp (for example, Windows file times have a resolution of, at best, 100-nanoseconds). You already have ModTime() so don't call os.Stat(). Use time.Time methods directly. And so on.
For example,
package main
import (
"fmt"
"io/ioutil"
"os"
"time"
)
func main() {
dir := `C:\temp\` // Windows directory
files, err := ioutil.ReadDir(dir)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
var modTime time.Time
var names []string
for _, fi := range files {
if fi.Mode().IsRegular() {
if !fi.ModTime().Before(modTime) {
if fi.ModTime().After(modTime) {
modTime = fi.ModTime()
names = names[:0]
}
names = append(names, fi.Name())
}
}
}
if len(names) > 0 {
fmt.Println(modTime, names)
}
}
You can just compare the outputs of fi.ModTime().Unix() and keep the largest value to find the most recently modified file.
For example:
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
dir := "/tmp/"
files, _ := ioutil.ReadDir(dir)
var newestFile string
var newestTime int64 = 0
for _, f := range files {
fi, err := os.Stat(dir + f.Name())
if err != nil {
fmt.Println(err)
}
currTime := fi.ModTime().Unix()
if currTime > newestTime {
newestTime = currTime
newestFile = f.Name()
}
}
fmt.Println(newestFile)
}

Writing buffer to file doesn't return error, so why is file empty afterwords?

I'm trying to read all standard input and write it to a file. It's writing nothing to the file provided. Why is it not working?
package main
import (
"os"
"bytes"
"fmt"
"bufio"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
fi, _ := os.Open(fn)
defer fi.Close()
fi.Write(input.Bytes())
}
And then...
touch writetothis.txt
echo "input text" | go run main.go writetothis.txt
# writetothis.txt is empty
Open opens a file in read-only mode.
Refer to documentation: https://golang.org/pkg/os/#Open
Instead, use OpenFile.
Also, always check for errors whenever you code. It'll save you at least weeks of work-hours in your lifetime.
Here is a working code:
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
fmt.Println(input.Bytes())
fi, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
fmt.Println("Error with Open()",err)
}
defer fi.Close()
n, err := fi.Write(input.Bytes())
if err != nil {
fmt.Println("Error with Write()", err)
}
fmt.Println("Bytes written to file: ",n)
}
In your code you can silently fail because you aren't checking the error. It's likely a path issue. You can change your code slightly and let ioutil handle file creation so that paths aren't so much of an issue. Remember to always check the errs
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
err := ioutil.WriteFile(fn, input.Bytes(), 0644)
if err != nil {
log.Fatal(err)
}
}

Save an image from url to file

Very new to Go (first simple project I'm working on).
Question: How do I get an image from URL and then save it to my computer?
Here's what I have so far:
package main
import (
"fmt"
"net/http"
"image"
"io/ioutil"
)
func main() {
url := "http://i.imgur.com/m1UIjW1.jpg"
// don't worry about errors
response, _ := http.Get(url);
defer response.Body.Close()
m, _, err := image.Decode(response.Body)
error := ioutil.WriteFile("/images/asdf.jpg", m, 0644)
}
However, when I run this code, I get cannot use m (type image.Image) as type []byte in function argument
I'm assuming I have to convert image.Image (variable m) into an undefined amount of bytes? Is that the correct way to go about this?
There is no need to decode the file. Simply copy the response body to a file you've opened. Here's the deal in the modified example:
response.Body is a stream of data, and implements the Reader interface - meaning you can sequentially call Read on it, as if it was an open file.
The file I'm opening here implements the Writer interface. This is the opposite - it's a stream you can call Write on.
io.Copy "patches" a reader and a writer, consumes the reader stream and writes its contents to a Writer.
This is one of my favorite things about go - implicit interfaces. You don't have to declare you're implementing an interface, you just have to implement it to be used in some context. This allows mixing and matching of code that doesn't need to know about other code it's interacting with.
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
)
func main() {
url := "http://i.imgur.com/m1UIjW1.jpg"
// don't worry about errors
response, e := http.Get(url)
if e != nil {
log.Fatal(e)
}
defer response.Body.Close()
//open a file for writing
file, err := os.Create("/tmp/asdf.jpg")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// Use io.Copy to just dump the response body to the file. This supports huge files
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Success!")
}
package main
import (
"io"
"net/http"
"os"
"fmt"
)
func main() {
img, _ := os.Create("image.jpg")
defer img.Close()
resp, _ := http.Get("http://i.imgur.com/Dz2r9lk.jpg")
defer resp.Body.Close()
b, _ := io.Copy(img, resp.Body)
fmt.Println("File size: ", b)
}
Try this:
package main
import (
"fmt"
"net/http"
"net/url"
"os"
"strings"
)
var (
fileName string
fullUrlFile string
)
func main() {
fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
r, e := http.Get(fullUrlFile)
if e != nil {
panic(e)
}
defer r.Body.Close()
buildFileName()
// Create distination
f, e := os.Create(fileName) // "m1UIjW1.jpg"
if e != nil {
panic(e)
}
defer f.Close()
// Fill distination with content
n, e := f.ReadFrom(r.Body)
if e != nil {
panic(e)
}
fmt.Println("File size: ", n)
}
func buildFileName() {
fileUrl, e := url.Parse(fullUrlFile)
if e != nil {
panic(e)
}
path := fileUrl.Path
segments := strings.Split(path, "/")
fileName = segments[len(segments)-1]
println(fileName)
}
You can also use the ReadFrom method:
package main
import (
"net/http"
"os"
)
func main() {
r, e := http.Get("https://i.imgur.com/m1UIjW1.jpg")
if e != nil {
panic(e)
}
defer r.Body.Close()
f, e := os.Create("m1UIjW1.jpg")
if e != nil {
panic(e)
}
defer f.Close()
f.ReadFrom(r.Body)
}
https://golang.org/pkg/os#File.ReadFrom
What is the type of response.Body? You should just convert that into a []byte if it is not and write that to disk. There is no reason to use the image class unless you have some reason to treat the data as an image. Just treat the data as a series of bytes and write it to the disk.

Resources