shadertoy_client 1.0.0-dev.4

shadertoy_client #

A Shadertoy API HTTP client implementation

Pub Package Build Status Coverage Status Package Documentation GitHub License

Introduction #

This package implements the client API's defined in the shadertoy_api package providing access to the Shadertoy REST and Site APIs.

Capabilities #

This package provides a number of operations through two types of clients:

REST APIs

  • Find shader by id
  • Find shaders from a list of id's
  • Query shaders by term, tags and sort them by name, likes, views, neweness and by hotness (proportional to popularity and inversly propostional to lifetime). All the query results are paginated.
  • Find all shader ids
  • Find shaders ids by term, tags and sort them by name, likes, views, neweness and by hotness (proportional to popularity and inversly propostional to lifetime). All the query results are paginated.

Site APIs

All the REST API features plus the following:

  • Login
  • Logout
  • Find user by id
  • Find shaders by user id
  • Query shaders by user id, tags and sort them by name, likes, views, neweness and by hotness (proportional to popularity and inversly propotional to lifetime). All the query results are paginated as well.
  • Find comments by shader id
  • Find playlist by id.
  • Query shaders by playlist id. All the query results are paginated.
  • Query shader ids by playlist id. All the query results are paginated.
  • Download preview, i.e. the the shader thumbnails
  • Download media, any other media provided by the Shadertoy website

Getting Started #

Add this to your pubspec.yaml (or create it):

dependencies:
    shadertoy_client: ^1.0.0-dev.4

Run the following command to install dependencies:

pub install

Optionally use the following command to run the tests:

pub run test

Finaly, to start developing import the library:

import 'package:shadertoy_client/shadertoy_client.dart';

Usage #

You can use this library with one of the following classes:

  • ShadertoyWSClient, for the REST API. This client can only provide shaders made available with the public+api privacy settings
  • ShadertoySiteClient for the Site API. This client provides all the shaders currently available in the Shadertoy website
  • ShadertoyHybridClient, which allows the user to constrain the requests to shaders with public+api privacy settings while complementing the base REST API with some additional operations only available in the Site API.

ShadertoyWSClient #

Note: replace apiKey with the API key obtained in your user apps page

Query a shader by id #

    var apiKey = '<apiKey>';
    var client = ShadertoyWSClient.build(apiKey);
    var fsr = await client.findShaderById('3lsSzf');
    if (fsr.ok) {
        print('${fsr?.shader?.info?.id}');
        print('\tName: ${fsr?.shader?.info?.name}');
        print('\tUserName: ${fsr?.shader?.info?.userId}');
        print('\tDate: ${fsr?.shader?.info?.date}');
        print('\tDescription: ${fsr?.shader?.info?.description}');
        print('\tViews: ${fsr?.shader?.info?.views}');
        print('\tLikes: ${fsr?.shader?.info?.likes}');
        print('\tPublish Status: ${fsr?.shader?.info?.publishStatus.toString().split('.').last}');
        print('\tTags: ${fsr?.shader?.info?.tags?.join(',')}');
        print('\tFlags: ${fsr?.shader?.info?.flags}');
        print('\tLiked: ${fsr?.shader?.info?.hasLiked}');
        print('\tRender Passes: ${fsr?.shader?.renderPasses?.length}');
        fsr?.shader?.renderPasses?.forEach((rp) => print('\t\t${rp?.name} has ${rp?.inputs?.length} input(s) and ${rp?.outputs?.length} output(s)'));
    } else {
        print('Error: ${fsr.error.message}');
    }

Output:

3lsSzf
	Name: Happy Jumping
	UserName: iq
	Date: 2019-07-25 00:49:38.000
	Description: A happy and blobby creature jumping. It gets off-model very often, but it looks good enough. Making of and related math/shader/art explanations (6 hours long): [url]https://www.youtube.com/watch?v=Cfe5UQ-1L9Q[/url]. 
	Views: 40436
	Likes: 358
	Publish Status: public_api
	Tags: procedural,3d,raymarching,sdf,animation
	Flags: 0
	Liked: false
	Render Passes: 1
		Image has 0 input(s) and 1 output(s)

Query shaders by term:

    var apiKey = '<apiKey>';
    var client = ShadertoyWSClient.build(apiKey);
    var fsr = await ws.findShaders(term: 'elevated');
    if (fsr.ok) {
        print('${fsr.total} shader id(s) found');
        response?.shaders?.forEach((sh) {
            print('${sh?.shader?.info?.name}');
        });
    } else {
        print('Error: ${fsr.error.message}');
    }

and the output, with the returned shader id's matching the term:

10 shader id(s) found
MdX3Rr 
MdBGzG 
lslBz7 
MtK3Wc 
XlXGzS 
XdKGW1 
ltd3Wl 
4sdXD4 
MsfcR8 
XltSWH 

ShadertoySiteClient #

Note: replace user and password, with the user credentials, where aplicable

Find a shader by id using a anonymous site client #

  var client = ShadertoySiteClient.build();

  var fsr = await ws.findShaderById('3lsSzf');
  if (fsr.ok) {
    print('${fsr?.shader?.info?.id}');
    print('\tName: ${fsr?.shader?.info?.name}');
    print('\tUserName: ${fsr?.shader?.info?.userId}');
    print('\tDate: ${fsr?.shader?.info?.date}');
    print('\tDescription: ${fsr?.shader?.info?.description}');
    print('\tViews: ${fsr?.shader?.info?.views}');
    print('\tLikes: ${fsr?.shader?.info?.likes}');
    print('\tPublish Status: ${fsr?.shader?.info?.publishStatus.toString().split('.').last}');
    print('\tTags: ${fsr?.shader?.info?.tags?.join(',')}');
    print('\tFlags: ${fsr?.shader?.info?.flags}');
    print('\tLiked: ${fsr?.shader?.info?.hasLiked}');
    print('\tRender Passes: ${fsr?.shader?.renderPasses?.length}');
    sr?.shader?.renderPasses?.forEach((rp) => print('\t\t${rp?.name} has ${rp?.inputs?.length} input(s) and ${rp?.outputs?.length} output(s)'));
  } else {
    print('Error: ${fsr.error.message}');
  }

Output:

3lsSzf
	Name: Happy Jumping
	UserName: iq
	Date: 2019-07-25 00:49:38.000
	Description: A happy and blobby creature jumping. It gets off-model very often, but it looks good enough. Making of and related math/shader/art explanations (6 hours long): [url]https://www.youtube.com/watch?v=Cfe5UQ-1L9Q[/url]. 
	Views: 40700
	Likes: 358
	Publish Status: public_api
	Tags: procedural,3d,raymarching,sdf,animation
	Flags: 0
	Liked: false
	Render Passes: 1
		Image has 0 input(s) and 1 output(s)

Anonymous usage of the site client versus logged in usage #


  var client =
      ShadertoySiteClient.build(user: '<user>', password: '<password>');

  print('Anonymous');
  var fsr = await client.findShaderById('3lsSzf');
  print('${fsr?.shader?.info?.id}');
  print('\tName: ${fsr?.shader?.info?.name}');
  print('\tLiked: ${fsr?.shader?.info?.hasLiked}');

  await site.login();

  print('Logged In');
  site.cookies.forEach((c) => print('${c.name}=${c.value}'));
  fsr = await client.findShaderById('3lsSzf');
  print('${fsr?.shader?.info?.id}');
  print('\tName: ${fsr?.shader?.info?.name}');
  print('\tLiked: ${fsr?.shader?.info?.hasLiked}');

Notice that the liked flag flips from false to true after the login

Anonymous
3lsSzf
        Name: Happy Jumping
        Liked: false
Logged In
sdtd=ed42bec0ab3f881fa7f180f1346dd6f9
3lsSzf
        Name: Happy Jumping
        Liked: true

Find shader comments #

  var client = ShadertoySiteClient.build();

  var fcr = await client.findCommentsByShaderId('MdX3Rr');
  if (fcr.ok) {
    print('${fcr?.total} comment(s)');
  } else {
    print('Error: ${fcr.error.message}');
  }

Output:

30 comment(s)

Find a user by id #

  var client = ShadertoySiteClient.build();

  var fur = await client.findUserById('iq');
  if (fur.ok) {
    print('${fur?.user?.id}');
    print('Name: ${fur?.user?.picture}');
    print('Member Since: ${fur?.user?.memberSince}');
    print('Shaders: ${fur?.user?.shaders}');
    print('Comments: ${fur?.user?.comments}');
    print('About:');
    print('${fur?.user?.about}');
  } else {
    print('Error: ${fur.error.message}');
  }

Output:

iq
Name: /media/users/iq/profile.png
Member Since: 2013-01-11 00:00:00.000
Shaders: 451
Comments: 4864
About:


*[url]http://www.iquilezles.org[/url]
*[url]https://www.patreon.com/inigoquilez[/url]
*[url]https://www.youtube.com/c/InigoQuilez[/url]
*[url]https://www.facebook.com/inigo.quilez.art[/url]
*[url]https://twitter.com/iquilezles[/url]

Find playlist by id #

  var client = ShadertoySiteClient.build();

  var fpr = await client.findPlaylistById('week');
  if (fcr.ok) {
    print('${fpr?.playlist?.name}');
    print('${fpr?.playlist?.count} shader id(s)');
    fpr.playlist?.shaders?.forEach((shader) => print('$shader'));
  } else {
    print('Error: ${fpr.error.message}');
  }

Output:

Shaders of the Week
339 shader id(s)
ttXGWH
ttlGR4
tsKXR3
WtsGzB
WtfGWn
3ddGzn
...

ShadertoyHybridClient #

Note: replace apiKey with the API key obtained in your user apps page

Find shader by term and obtain the shader comments

  var client = ShadertoyHybridClient.build(apiKey: '<apiKey>');
  var fsr = await client.findShaders(term: 'Happy Jumping');

  if (fsr.ok) {
    if (fsr.shaders.isNotEmpty) {
      var fsc = await client.findCommentsByShaderId(fsr?.shaders?.first?.shader?.info?.id);
      if (fsc.ok) {
        print('Found ${fsc.comments.length} comments');
      } else {
        print('Error retrieving shader comments');
      }
    } else {
      print('Shader not found');
    }
  } else {
    print('Error: ${fsr.error.message}');
  }

Output:

3lsSzf
        Name: Happy Jumping
Found 62 comments

Contributing #

This a unofficial Shadertoy client library. It is developed by best effort, in the motto of "Scratch your own itch!", meaning APIs that are meaningful for the author use cases.

If you would like to contribute with other parts of the API, feel free to make a Github pull request as I'm always looking for contributions for:

  • Tests
  • Documentation
  • New APIs

Features and Bugs #

Please file feature requests and bugs at the issue tracker.

License #

This project is licensed under the MIT License - see the LICENSE file for details

1.0.0-dev.4 #

  • Added enum_to_string dependency to work better with enums
  • Reverted to debugConsole
  • Updated to next version of the API

1.0.0-dev.3 #

  • Updated badges
  • Updated dart sdk to 2.7
  • Added documentation
  • Updated dependencies
  • Corrected bugs after applying the linter
  • Added hybrid examples
  • VS code now uses the terminal to launch the examples

1.0.0-dev.2 #

  • Corrected codecov badge link in the README file

1.0.0-dev.1 #

  • Initial version

example/example.dart

import 'package:dotenv/dotenv.dart';
import 'package:enum_to_string/enum_to_string.dart';
import 'package:shadertoy_client/shadertoy_client.dart';

void main(List<String> arguments) async {
  // Reads environment variables from a .env file.
  // Create .env file at the root of the project and set
  // the apiKey e.g. `apiKey='XXXXXX'`. This project uses the
  // dotenv package to load values at bootstrap
  load();

  // If the api key is not specified in the arguments, try the environment one
  var apiKey = arguments.isEmpty ? env['apiKey'] : arguments[0];

  // if no api key is found abort
  if (apiKey == null || apiKey.isEmpty) {
    print('Invalid API key');
    return;
  }

  var ws = ShadertoyWSClient.build(apiKey);
  var site = ShadertoySiteClient.build();

  // Gets the shader by id
  var shaderId = '3lsSzf';
  var sr = await ws.findShaderById(shaderId);
  if (sr.ok) {
    // If there is no error print the shader contents
    print('${sr?.shader?.info?.id}');
    print('\tName: ${sr?.shader?.info?.name}');
    print('\tUserName: ${sr?.shader?.info?.userId}');
    print('\tDate: ${sr?.shader?.info?.date}');
    print('\tDescription: ${sr?.shader?.info?.description}');
    print('\tViews: ${sr?.shader?.info?.views}');
    print('\tLikes: ${sr?.shader?.info?.likes}');
    print(
        '\tPublish Status: ${EnumToString.parse(sr?.shader?.info?.publishStatus)}');
    print('\tTags: ${sr?.shader?.info?.tags?.join(',')}');
    print('\tFlags: ${sr?.shader?.info?.flags}');
    print('\tLiked: ${sr?.shader?.info?.hasLiked}');
    print('\tRender Passes: ${sr?.shader?.renderPasses?.length}');
    sr?.shader?.renderPasses?.forEach((element) => print(
        '\t\t${element?.name} has ${element?.inputs?.length} input(s) and ${element?.outputs?.length} output(s)'));
  } else {
    // In case of error print the error message
    print('Error retrieving the shader: ${sr.error.message}');
  }

  // Gets the firs 5 comments for this shader
  var sc = await site.findCommentsByShaderId(shaderId);
  if (sc.ok) {
    // If there is no error print the shader comments
    sc?.comments?.take(5)?.forEach((c) => print('${c.userId}: ${c.text}'));
  } else {
    // In case of error print the error message
    print('Error retrieving shader ${shaderId} comments: ${sr.error.message}');
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  shadertoy_client: ^1.0.0-dev.4

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:shadertoy_client/shadertoy_client.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
15
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
95
Overall:
Weighted score of the above. [more]
57
Learn more about scoring.

We analyzed this package on Feb 12, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.5

Maintenance suggestions

Package is pre-release. (-5 points)

Pre-release versions should be used with caution; their API can change in breaking ways.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
cookie_jar ^1.0.1 1.0.1
dio ^3.0.7 3.0.8
dio_cookie_manager ^1.0.0 1.0.0
dotenv ^2.0.0 2.0.0
enum_to_string ^1.0.8 1.0.8
equatable ^1.0.1 1.1.0
html ^0.14.0+3 0.14.0+3
intl ^0.16.0 0.16.1
json_annotation ^3.0.0 3.0.1
meta ^1.1.8 1.1.8
path ^1.6.4 1.6.4
pool ^1.4.0 1.4.0
retry ^3.0.0+1 3.0.0+1
shadertoy_api ^1.0.0-dev.7 1.0.0-dev.7
Transitive dependencies
args 1.5.2
async 2.4.0
charcode 1.1.3
collection 1.14.12
csslib 0.16.1
dart2_constant 1.0.2+dart2
http_parser 3.1.3
source_span 1.6.0
stack_trace 1.9.3
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
Dev dependencies
build_runner ^1.7.2
build_verify ^1.1.1
json_serializable ^3.2.3
mockito ^4.1.1
pedantic ^1.9.0
test ^1.9.4
test_coverage ^0.4.0