Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,49 @@ def main(config):
print("You win!")
else:
print("Better luck next time!")
```

## Pixlet module: QRCode

The `qrcode` module provides a QR code generator for pixlet!

| Function | Description |
| --- | --- |
| `generate(url, size, color?, background?)` | Returns a QR code as an image that can be passed into the image widget. |

Sizing works as follows:
- `small`: 21x21 pixels
- `medium`: 25x25 pixels
- `large`: 29x29 pixels

Note: we're working with some of the smallest possible QR codes in this module, so the amount of data that can be used for the URL is extremely limited.

Example:
```starlark
load("cache.star", "cache")
load("encoding/base64.star", "base64")
load("render.star", "render")
load("qrcode.star", "qrcode")

def main(config):
url = "https://tidbyt.com?utm_source=pixlet_example"

data = cache.get(url)
if data == None:
code = qrcode.generate(
url = url,
size = "large",
color = "#fff",
background = "#000",
)
cache.set(url, base64.encode(code), ttl_seconds = 3600)
else:
code = base64.decode(data)

return render.Root(
child = render.Padding(
child = render.Image(src = code),
pad = 1,
),
)
```
26 changes: 26 additions & 0 deletions examples/qrcode.star
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
load("cache.star", "cache")
load("encoding/base64.star", "base64")
load("render.star", "render")
load("qrcode.star", "qrcode")

def main(config):
url = "https://tidbyt.com?utm_source=pixlet_example"

data = cache.get(url)
if data == None:
code = qrcode.generate(
url = url,
size = "large",
color = "#fff",
background = "#000",
)
cache.set(url, base64.encode(code), ttl_seconds = 3600)
else:
code = base64.decode(data)

return render.Root(
child = render.Padding(
child = render.Image(src = code),
pad = 1,
),
)
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/pkg/errors v0.9.1
github.com/qri-io/starlib v0.5.1-0.20211102160121-ae835e29cd41
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.8.0
github.com/tidbyt/go-libwebp v0.0.0-20220302154536-6042ce446e9c
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
Expand Down
4 changes: 4 additions & 0 deletions runtime/applet.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"tidbyt.dev/pixlet/render"
"tidbyt.dev/pixlet/runtime/modules/animation_runtime"
"tidbyt.dev/pixlet/runtime/modules/humanize"
"tidbyt.dev/pixlet/runtime/modules/qrcode"
"tidbyt.dev/pixlet/runtime/modules/random"
"tidbyt.dev/pixlet/runtime/modules/render_runtime"
"tidbyt.dev/pixlet/runtime/modules/sunrise"
Expand Down Expand Up @@ -347,6 +348,9 @@ func (a *Applet) loadModule(thread *starlark.Thread, module string) (starlark.St
case "random.star":
return random.LoadModule()

case "qrcode.star":
return qrcode.LoadModule()

case "assert.star":
return starlarktest.LoadAssertModule()

Expand Down
109 changes: 109 additions & 0 deletions runtime/modules/qrcode/qrcode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package qrcode

import (
"fmt"
"image/color"
"sync"

goqrcode "github.com/skip2/go-qrcode"
"go.starlark.net/starlark"
"go.starlark.net/starlarkstruct"
"tidbyt.dev/pixlet/render"
)

const (
ModuleName = "qrcode"
)

var (
once sync.Once
module starlark.StringDict
)

func LoadModule() (starlark.StringDict, error) {
once.Do(func() {
module = starlark.StringDict{
ModuleName: &starlarkstruct.Module{
Name: ModuleName,
Members: starlark.StringDict{
"generate": starlark.NewBuiltin("generate", generateQRCode),
},
},
}
})

return module, nil
}

func generateQRCode(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var (
starUrl starlark.String
starSize starlark.String
starColor starlark.String
starBackground starlark.String
)

if err := starlark.UnpackArgs(
"generate",
args, kwargs,
"url", &starUrl,
"size", &starSize,
"color?", &starColor,
"background?", &starBackground,
); err != nil {
return nil, fmt.Errorf("unpacking arguments for generate: %w", err)
}

// Determine QRCode sizing information.
version := 0
imgSize := 0
switch starSize.GoString() {
case "small":
version = 1
imgSize = 21
case "medium":
version = 2
imgSize = 25
case "large":
version = 3
imgSize = 29
default:
return nil, fmt.Errorf("size must be small, medium, or large")
}

url := starUrl.String()
code, err := goqrcode.NewWithForcedVersion(url, version, goqrcode.Low)
if err != nil {
return nil, err
}

// Set default styles.
code.DisableBorder = true
code.ForegroundColor = color.White
code.BackgroundColor = color.Transparent

// Override color if one is provided.
if starColor.Len() > 0 {
color, err := render.ParseColor(starColor.GoString())
if err != nil {
return nil, fmt.Errorf("color is not a valid hex string: %s", starColor.String())
}
code.ForegroundColor = color
}

// Override background if one is provided.
if starBackground.Len() > 0 {
background, err := render.ParseColor(starBackground.GoString())
if err != nil {
return nil, fmt.Errorf("color is not a valid hex string: %s", starColor.String())
}
code.BackgroundColor = background
}

png, err := code.PNG(imgSize)
if err != nil {
return nil, err
}

return starlark.String(string(png)), nil
}
38 changes: 38 additions & 0 deletions runtime/modules/qrcode/qrcode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package qrcode_test

import (
"testing"

"github.com/stretchr/testify/assert"
"tidbyt.dev/pixlet/runtime"
)

var qrCodeSource = `
load("qrcode.star", "qrcode")

def assert(success, message=None):
if not success:
fail(message or "assertion failed")


url = "https://tidbyt.com?utm_source=pixlet_example"
code = qrcode.generate(
url = url,
size = "large",
color = "#fff",
background = "#000",
)

def main():
return []
`

func TestQRCode(t *testing.T) {
app := &runtime.Applet{}
err := app.Load("test.star", []byte(qrCodeSource), nil)
assert.NoError(t, err)

screens, err := app.Run(map[string]string{})
assert.NoError(t, err)
assert.NotNil(t, screens)
}