*: moving to a repo

Since this was initially on
https://gist.github.com/vbatts/ed28cddc23d6d2123e0c0295b278471b

Folks asked for this to be `go get`'able.

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
Vincent Batts 2016-12-02 11:32:31 -05:00
parent b049d4d104
commit a8885e2038
Signed by: vbatts
GPG Key ID: 10937E57733F1362
2 changed files with 498 additions and 0 deletions

57
README.md Normal file
View File

@ -0,0 +1,57 @@
# emojisum
:pray: :paperclip: Emoji that checksum! :tada: :poop:
I attempted a curated list of 256 emojis that are not entirely similar. Using http://www.webpagefx.com/tools/emoji-cheat-sheet/ to compare them. I went with 256 as that is 8bit/1byte, and the hexadecimal output that is 2 hex characters.
So 1 emoji is 2 hex positions.
## build
```bash
go get github.com/vbatts/emojisum
```
## usage
This uses [`github.com/kyokomi/emoji`](https://github.com/kyokomi/emoji) to print to the console, but also gives the string ouptut for easy pasting to github/markdown.
```bash
$> emojisum main.go
SHA1(main.go)= 14b09535217ca8f5f47f4665e2266e686f0728b4
SHA1(main.go)= :bird::red_car::on::crystal_ball::calendar::lemon::pray::warning::violin::lollipop::facepunch::hearts::tm::children_crossing::hourglass::heavy_plus_sign::house::ant::clap::rocket:
SHA1(main.go)= 🐦 🚗 🔛 🔮 📆 🍋 🙏 ⚠️🎻 🍭 👊 ♥️™️🚸 ⌛️➕ 🏠 🐜 👏 🚀
```
Like so!
SHA1(main.go)= :bird::red_car::on::crystal_ball::calendar::lemon::pray::warning::violin::lollipop::facepunch::hearts::tm::children_crossing::hourglass::heavy_plus_sign::house::ant::clap::rocket:
### pass in the checksums
Rather than relying on this simple tool to do the checksum itself, you will likely want to rely on OpenSSL or coreutils for checksumming.
`emojisum` can just take those formats on stdin:
```bash
$> sha1sum main.go | emojisum -parse-coreutils
7656835947b4c6da272023c56b6f2529511bf88b main.go
:jp::gb::metal::goat::family::rocket::smiley_cat::swimmer::chocolate_bar::cactus::candy::smile::honeybee::house::cherries::cloud::fries::bow::wavy_dash::musical_score: main.go
🇯🇵 🇬🇧 🤘 🐐 👪 🚀 😺 🏊 🍫 🌵 🍬 😄 🐝 🏠 🍒 ☁️🍟 🙇 〰️ 🎼 main.go
```
Like so:
🇯🇵 🇬🇧 🤘 🐐 👪 🚀 😺 🏊 🍫 🌵 🍬 😄 🐝 🏠 🍒 ☁️🍟 🙇 〰️ 🎼 main.go
```bash
$> openssl sha1 main.go |emojisum -parse-openssl
SHA1(main.go)= 7656835947b4c6da272023c56b6f2529511bf88b
SHA1(main.go)= :jp::gb::metal::goat::family::rocket::smiley_cat::swimmer::chocolate_bar::cactus::candy::smile::honeybee::house::cherries::cloud::fries::bow::wavy_dash::musical_score:
SHA1(main.go)= 🇯🇵 🇬🇧 🤘 🐐 👪 🚀 😺 🏊 🍫 🌵 🍬 😄 🐝 🏠 🍒 ☁️🍟 🙇 〰️ 🎼
```
And like so:
SHA1(main.go)= 🇯🇵 🇬🇧 🤘 🐐 👪 🚀 😺 🏊 🍫 🌵 🍬 😄 🐝 🏠 🍒 ☁️🍟 🙇 〰️ 🎼

441
main.go Normal file
View File

@ -0,0 +1,441 @@
package main
import (
"bufio"
"crypto/sha1"
"encoding/hex"
"errors"
"flag"
"fmt"
"io"
"os"
"strings"
"github.com/kyokomi/emoji"
)
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
var (
flParseOpenSSL = flag.Bool("parse-openssl", false, "parse the output of OpenSSL style checksums on stdin (`openssl sha256 ./foo | emojisum -parse-openssl`)")
flParseCoreUtils = flag.Bool("parse-coreutils", false, "parse the output of CoreUtils style checksums on stdin (`sha256sum ./foo | emojisum -parse-coreutils`)")
)
func run() error {
flag.Parse()
if *flParseOpenSSL {
buf := bufio.NewReader(os.Stdin)
for {
line, err := buf.ReadString('\n')
if err != nil && err == io.EOF {
return nil
} else if err != nil {
return err
}
hash, name, sum, err := parseOpenSSL(line)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %q\n", err, line)
continue
}
str := emojiFromBytes(sum)
fmt.Printf("%s(%s)= %x\n", hash, name, sum)
fmt.Printf("%s(%s)= %s\n", hash, name, str)
fmt.Printf("%s(%s)= ", hash, name)
emoji.Println(str)
}
return nil
}
if *flParseCoreUtils {
buf := bufio.NewReader(os.Stdin)
for {
line, err := buf.ReadString('\n')
if err != nil && err == io.EOF {
return nil
} else if err != nil {
return err
}
name, sum, err := parseCoreUtils(line)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %q\n", err, line)
continue
}
str := emojiFromBytes(sum)
fmt.Printf("%x %s\n", sum, name)
fmt.Printf("%s %s\n", str, name)
emoji.Print(str)
fmt.Printf(" %s\n", name)
}
return nil
}
// Otherwise do the checksum ourselves
if flag.NArg() == 0 {
sum, err := Sum(os.Stdin)
if err != nil {
return err
}
str := emojiFromBytes(sum)
fmt.Printf("SHA1(-)=\t%x\n", sum)
fmt.Printf("SHA1(-)=\t%s\n", str)
fmt.Printf("SHA1(-)=\t")
emoji.Println(str)
return nil
}
for _, arg := range flag.Args() {
fh, err := os.Open(arg)
if err != nil {
return err
}
defer fh.Close()
sum, err := Sum(fh)
if err != nil {
return err
}
str := emojiFromBytes(sum)
fmt.Printf("SHA1(%s)=\t%x\n", arg, sum)
fmt.Printf("SHA1(%s)=\t%s\n", arg, str)
fmt.Printf("SHA1(%s)=\t", arg)
emoji.Println(str)
}
return nil
}
/*
openssl sum:
```
$> openssl sha256 tmp.efLuko
SHA256(tmp.efLuko)= f18bd8b680e834ab8097a66deb0255821195d9624e39da6b65903ff6a09a01bb
```
*/
func parseOpenSSL(line string) (hash, filename string, sum []byte, err error) {
if !strings.Contains(line, "(") {
return "", "", nil, ErrNotOpenSSLLine
}
chunks := strings.SplitN(strings.TrimRight(line, "\n"), ")= ", 2)
if len(chunks) != 2 {
return "", "", nil, ErrNotOpenSSLLine
}
chunksprime := strings.SplitN(chunks[0], "(", 2)
if len(chunks) != 2 {
return "", "", nil, ErrNotOpenSSLLine
}
sum, err = hex.DecodeString(chunks[1])
if err != nil {
return "", "", nil, err
}
return chunksprime[0], chunksprime[1], sum, nil
}
var ErrNotOpenSSLLine = errors.New("not an openssl checksum line")
/*
coreutils output:
```
$ sha256sum ./tmp.efLuko
f18bd8b680e834ab8097a66deb0255821195d9624e39da6b65903ff6a09a01bb ./tmp.efLuko
```
*/
func parseCoreUtils(line string) (filename string, sum []byte, err error) {
chunks := strings.SplitN(strings.TrimRight(line, "\n"), " ", 2)
if len(chunks) != 2 {
return "", nil, ErrNotCoreUtilsLine
}
sum, err = hex.DecodeString(chunks[0])
if err != nil {
return "", nil, err
}
return chunks[1], sum, nil
}
var ErrNotCoreUtilsLine = errors.New("not a coreutils checksum line")
func Sum(r io.Reader) ([]byte, error) {
h := sha1.New()
if _, err := io.Copy(h, r); err != nil {
return nil, err
}
sum := h.Sum(nil)
return sum[:], nil
}
func emojiFromBytes(buf []byte) string {
var ret string
for _, b := range buf {
ret = ret + emojiFromRune(b)
}
return ret
}
func emojiFromRune(b byte) string {
//fmt.Printf("%#v\n", b)
return emojiMap[int(b)]
}
// these are an ordered list, referened by a byte (each byte of a checksum digest)
var emojiMap = []string{
":+1:",
":8ball:",
":airplane:",
":alien:",
":anchor:",
":angel:",
":angry:",
":ant:",
":apple:",
":art:",
":baby:",
":baby_bottle:",
":back:",
":bamboo:",
":banana:",
":barber:",
":bathtub:",
":beer:",
":bell:",
":bicyclist:",
":bird:",
":birthday:",
":blossom:",
":blue_car:",
":boar:",
":bomb:",
":boom:",
":bow:",
":boy:",
":broken_heart:",
":bulb:",
":bus:",
":cactus:",
":calendar:",
":camera:",
":candy:",
":cat:",
":cherries:",
":children_crossing:",
":chocolate_bar:",
":clap:",
":cloud:",
":clubs:",
":cn:",
":coffee:",
":construction:",
":cookie:",
":copyright:",
":corn:",
":cow:",
":crescent_moon:",
":crown:",
":cry:",
":crystal_ball:",
":curly_loop:",
":dancers:",
":dash:",
":de:",
":diamonds:",
":dog:",
":doughnut:",
":dragon:",
":dvd:",
":ear:",
":eggplant:",
":elephant:",
":end:",
":envelope:",
":es:",
":eyes:",
":facepunch:",
":family:",
":ferris_wheel:",
":finnadie:",
":fire:",
":fireworks:",
":floppy_disk:",
":football:",
":fork_and_knife:",
":four_leaf_clover:",
":fr:",
":fries:",
":frog:",
":fu:",
":full_moon:",
":game_die:",
":gb:",
":gem:",
":girl:",
":goat:",
":grimacing:",
":grin:",
":guardsman:",
":guitar:",
":gun:",
":hamburger:",
":hammer:",
":hamster:",
":hear_no_evil:",
":heart:",
":heart_eyes_cat:",
":hearts:",
":heavy_check_mark:",
":moyai:",
":izakaya_lantern:",
":helicopter:",
":hocho:",
":honeybee:",
":horse:",
":horse_racing:",
":hourglass:",
":house:",
":hurtrealbad:",
":icecream:",
":imp:",
":it:",
":jack_o_lantern:",
":japanese_goblin:",
":jp:",
":key:",
":kiss:",
":kissing_cat:",
":koala:",
":kr:",
":lemon:",
":lipstick:",
":lock:",
":lollipop:",
":man:",
":maple_leaf:",
":mask:",
":metal:",
":microscope:",
":moneybag:",
":monkey:",
":mount_fuji:",
":muscle:",
":mushroom:",
":musical_keyboard:",
":musical_score:",
":nail_care:",
":new_moon:",
":no_entry:",
":nose:",
":notes:",
":nut_and_bolt:",
":o:",
":ocean:",
":ok_hand:",
":on:",
":package:",
":palm_tree:",
":panda_face:",
":paperclip:",
":partly_sunny:",
":passport_control:",
":paw_prints:",
":peach:",
":penguin:",
":phone:",
":pig:",
":pill:",
":pineapple:",
":pizza:",
":point_left:",
":point_right:",
":poop:",
":poultry_leg:",
":pray:",
":princess:",
":purse:",
":pushpin:",
":rabbit:",
":rainbow:",
":raised_hand:",
":recycle:",
":red_car:",
":registered:",
":ribbon:",
":rice:",
":rocket:",
":roller_coaster:",
":rooster:",
":ru:",
":sailboat:",
":santa:",
":satellite:",
":satisfied:",
":saxophone:",
":scissors:",
":see_no_evil:",
":sheep:",
":shell:",
":shoe:",
":ski:",
":skull:",
":sleepy:",
":smile:",
":smiley_cat:",
":smirk:",
":smoking:",
":snail:",
":snake:",
":snowflake:",
":soccer:",
":soon:",
":space_invader:",
":spades:",
":speak_no_evil:",
":star:",
":stars:",
":statue_of_liberty:",
":steam_locomotive:",
":sunflower:",
":sunglasses:",
":sunny:",
":sunrise:",
":surfer:",
":swimmer:",
":syringe:",
":tada:",
":tangerine:",
":taxi:",
":tennis:",
":tent:",
":thought_balloon:",
":tm:",
":toilet:",
":tongue:",
":tophat:",
":tractor:",
":trolleybus:",
":trollface:",
":trophy:",
":trumpet:",
":turtle:",
":two_men_holding_hands:",
":two_women_holding_hands:",
":uk:",
":umbrella:",
":unlock:",
":us:",
":v:",
":vhs:",
":violin:",
":warning:",
":watermelon:",
":wave:",
":wavy_dash:",
":wc:",
":wheelchair:",
":woman:",
":x:",
":yum:",
":zap:",
":zzz:",
}