├── .dockerignore ├── .github └── workflows │ ├── build-test-lint.yml │ ├── docker-images.yml │ └── release.yml ├── .gitignore ├── API.md ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── config.example.json ├── go.mod ├── go.sum ├── http_root ├── css │ ├── bootstrap.min.css │ ├── screen.css │ └── squashed.css ├── favicon │ ├── browserconfig.xml │ ├── favicon-114.png │ ├── favicon-120.png │ ├── favicon-144.png │ ├── favicon-150.png │ ├── favicon-152.png │ ├── favicon-16.png │ ├── favicon-160.png │ ├── favicon-180.png │ ├── favicon-192.png │ ├── favicon-310.png │ ├── favicon-32.png │ ├── favicon-57.png │ ├── favicon-60.png │ ├── favicon-64.png │ ├── favicon-70.png │ ├── favicon-72.png │ ├── favicon-76.png │ ├── favicon-96.png │ └── favicon.ico ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── images │ ├── unknownAlbum.png │ └── unknownArtist.png ├── js │ ├── Jplayer.swf │ ├── URI.min.js │ ├── add-on │ │ ├── jplayer.playlist.min.js │ │ └── jquery.jplayer.inspector.js │ ├── app.js │ ├── bootstrap.min.js │ ├── debug │ │ ├── bootstrap.js │ │ ├── jplayer.playlist.js │ │ ├── jquery.jplayer.js │ │ └── jquery.js │ ├── ie8 │ │ ├── html5shiv.js │ │ └── respond.min.js │ ├── jquery.jplayer.min.js │ ├── jquery.min.js │ └── squashed.js ├── login │ └── index.html ├── skin │ └── blue.monday │ │ ├── jplayer.blue.monday.css │ │ ├── jplayer.blue.monday.jpg │ │ ├── jplayer.blue.monday.seeking.gif │ │ └── jplayer.blue.monday.video.play.png └── squash ├── images ├── barded-spice-install-step1.png ├── barded-spice-install-step2.png ├── barded-spice-install-step3.png ├── euterpe-preview.webp └── heavy-metal-128.png ├── main.go ├── sqls ├── library_schema.sql └── migrations │ ├── 001_album_artworks.sql │ ├── 002_uniqueness.sql │ ├── 003_track_duration.sql │ ├── 004_artists_images.sql │ ├── 005_small_images.sql │ ├── 006_stats.sql │ ├── 007_album_artist_stats.sql │ ├── 008_more_track_columns.sql │ ├── 009_internet_radio.sql │ ├── 010_playlists.sql │ └── 011_playlists_uniqe_index.sql ├── src ├── art │ ├── album.go │ ├── album_test.go │ ├── art.go │ ├── artfakes │ │ ├── fake_caaclient.go │ │ └── fake_finder.go │ ├── artist.go │ ├── artist_test.go │ ├── caa_client.go │ ├── client_test_helpers.go │ ├── client_unexported_test.go │ ├── doc.go │ └── generate.go ├── assert │ ├── assertfakes │ │ └── fake_testing_fatalf.go │ ├── common.go │ ├── equal.go │ ├── equal_test.go │ ├── nils.go │ └── nils_test.go ├── config │ ├── config.go │ └── config_test.go ├── daemon │ ├── daemon_nix.go │ ├── daemon_test.go │ ├── daemon_win.go │ └── doc.go ├── helpers │ ├── helpers.go │ ├── helpers_nix.go │ ├── helpers_test.go │ └── helpers_win.go ├── library │ ├── artist_images.go │ ├── artist_images_test.go │ ├── artwork.go │ ├── artwork_common.go │ ├── artwork_test.go │ ├── browser.go │ ├── bytes_read_closer.go │ ├── database.go │ ├── format.go │ ├── generate.go │ ├── library.go │ ├── library_test.go │ ├── library_watch_test.go │ ├── libraryfakes │ │ ├── fake_artist_image_manager.go │ │ ├── fake_artwork_manager.go │ │ ├── fake_browser.go │ │ └── fake_library.go │ ├── local_browse.go │ ├── local_browse_test.go │ ├── local_database_utils.go │ ├── local_favourites.go │ ├── local_favourites_test.go │ ├── local_library.go │ ├── local_library_cleanup.go │ ├── local_library_cleanup_test.go │ ├── local_library_migrate.go │ ├── local_library_scan.go │ ├── local_library_watch.go │ ├── local_ratings.go │ ├── local_ratings_test.go │ ├── media_file.go │ ├── media_file_test.go │ ├── mock_media_test.go │ ├── os_fs.go │ └── os_fs_test.go ├── main.go ├── playlists │ ├── generate.go │ ├── manager.go │ ├── playlists.go │ ├── playlists_test.go │ └── playlistsfakes │ │ └── fake_playlister.go ├── radio │ ├── generate.go │ ├── manager.go │ ├── radio.go │ ├── radio_test.go │ └── radiofakes │ │ └── fake_stations.go ├── scaler │ ├── doc.go │ ├── generate.go │ ├── scaler.go │ ├── scaler_test.go │ └── scalerfakes │ │ └── fake_scaler.go ├── tools │ └── tools.go ├── version │ ├── version.go │ └── version_test.go └── webserver │ ├── apiv1_endpoints.go │ ├── functions.go │ ├── functions_test.go │ ├── handler_about.go │ ├── handler_about_test.go │ ├── handler_access.go │ ├── handler_access_test.go │ ├── handler_album.go │ ├── handler_album_artwork.go │ ├── handler_album_artwork_test.go │ ├── handler_artist_images.go │ ├── handler_artist_images_test.go │ ├── handler_auth.go │ ├── handler_auth_test.go │ ├── handler_browse.go │ ├── handler_browse_test.go │ ├── handler_create_qr_token.go │ ├── handler_create_qr_token_test.go │ ├── handler_file.go │ ├── handler_file_test.go │ ├── handler_gzip.go │ ├── handler_login.go │ ├── handler_login_test.go │ ├── handler_login_token.go │ ├── handler_login_token_test.go │ ├── handler_logout.go │ ├── handler_logout_test.go │ ├── handler_playlist.go │ ├── handler_playlist_test.go │ ├── handler_playlists.go │ ├── handler_playlists_test.go │ ├── handler_register_token.go │ ├── handler_register_token_test.go │ ├── handler_search.go │ ├── handler_template.go │ ├── handler_terry.go │ ├── subsonic │ ├── auth.go │ ├── auth_test.go │ ├── base_responses.go │ ├── cover_art_interfaces.go │ ├── create_internet_radio_station.go │ ├── create_playlist.go │ ├── deleteInternetRadioStation.go │ ├── delete_playlist.go │ ├── errors.go │ ├── generate.go │ ├── get_album.go │ ├── get_album_info.go │ ├── get_album_info_2.go │ ├── get_album_list.go │ ├── get_album_list_2.go │ ├── get_artist.go │ ├── get_artist_info.go │ ├── get_artist_info_2.go │ ├── get_artist_info_2_test.go │ ├── get_artist_info_test.go │ ├── get_artists.go │ ├── get_cover_art.go │ ├── get_genres.go │ ├── get_indexes.go │ ├── get_internet_radion_stagions.go │ ├── get_license.go │ ├── get_music_directory.go │ ├── get_music_folders.go │ ├── get_open_subsonic_extensions.go │ ├── get_playlist.go │ ├── get_playlists.go │ ├── get_random_songs.go │ ├── get_song.go │ ├── get_starred.go │ ├── get_starred_2.go │ ├── get_top_songs.go │ ├── get_user.go │ ├── get_video_info.go │ ├── get_videos.go │ ├── http.go │ ├── id_conversion.go │ ├── index.go │ ├── open_subsonic_extensions_test.go │ ├── ping.go │ ├── progress.md │ ├── scrobble.go │ ├── search.go │ ├── search2.go │ ├── search3.go │ ├── set_rating.go │ ├── set_rating_test.go │ ├── star.go │ ├── stream.go │ ├── subsonic-rest-api-1.16.1.xsd │ ├── subsonicfakes │ │ └── fake_cover_art_handler.go │ ├── unstar.go │ ├── update_internet_radio_station.go │ ├── update_playlist.go │ ├── xml_xsd_vaidate_test.go │ └── xsd_types.go │ ├── templates.go │ ├── webserver.go │ ├── webserver_test.go │ └── webutils │ ├── doc.go │ ├── error.go │ └── error_test.go ├── templates ├── add_device.html ├── layout.html ├── player.html └── unauthorized.html ├── test_files ├── http_root │ ├── second │ │ └── static │ └── static ├── library │ ├── folder_one │ │ ├── not_an_mp3 │ │ └── third_file.mp3 │ ├── test_file_one.mp3 │ └── test_file_two.mp3 ├── more_mp3s │ └── test_file_added.mp3 ├── ogg_files │ └── vorbis-tags.ogg └── ssl │ ├── cert.pem │ └── key.pem ├── tools ├── bearded-spice.js ├── build ├── cross-compile ├── euterpe.service ├── install ├── nginx.conf └── uninstall ├── vendor ├── github.com │ ├── dhowden │ │ └── tag │ │ │ ├── .editorconfig │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── dsf.go │ │ │ ├── flac.go │ │ │ ├── id.go │ │ │ ├── id3v1.go │ │ │ ├── id3v2.go │ │ │ ├── id3v2frames.go │ │ │ ├── id3v2metadata.go │ │ │ ├── mp4.go │ │ │ ├── ogg.go │ │ │ ├── sum.go │ │ │ ├── tag.go │ │ │ ├── util.go │ │ │ └── vorbis.go │ ├── gbrlsnchs │ │ └── jwt │ │ │ └── v3 │ │ │ ├── .editorconfig │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── algorithm.go │ │ │ ├── audience.go │ │ │ ├── doc.go │ │ │ ├── ecdsa_sha.go │ │ │ ├── ed25519.go │ │ │ ├── ed25519_go1_12.go │ │ │ ├── hash_pool.go │ │ │ ├── header.go │ │ │ ├── hmac_sha.go │ │ │ ├── internal │ │ │ ├── decode.go │ │ │ ├── ed25519.go │ │ │ ├── ed25519_go1_12.go │ │ │ ├── epoch.go │ │ │ ├── errors.go │ │ │ └── errors_go1_12.go │ │ │ ├── json.go │ │ │ ├── magefile.go │ │ │ ├── none.go │ │ │ ├── payload.go │ │ │ ├── raw_token.go │ │ │ ├── resolver.go │ │ │ ├── rsa_sha.go │ │ │ ├── sign.go │ │ │ ├── time.go │ │ │ ├── validators.go │ │ │ └── verify.go │ ├── gorilla │ │ ├── context │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── context.go │ │ │ └── doc.go │ │ └── mux │ │ │ ├── .travis.yml │ │ │ ├── ISSUE_TEMPLATE.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── context_gorilla.go │ │ │ ├── context_native.go │ │ │ ├── doc.go │ │ │ ├── middleware.go │ │ │ ├── mux.go │ │ │ ├── regexp.go │ │ │ ├── route.go │ │ │ └── test_helpers.go │ ├── howeyc │ │ └── fsnotify │ │ │ ├── .gitignore │ │ │ ├── AUTHORS │ │ │ ├── CHANGELOG.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── fsnotify.go │ │ │ ├── fsnotify_bsd.go │ │ │ ├── fsnotify_linux.go │ │ │ ├── fsnotify_open_bsd.go │ │ │ ├── fsnotify_open_darwin.go │ │ │ └── fsnotify_windows.go │ ├── ironsmile │ │ ├── sql-migrate │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── migrate.go │ │ │ └── sqlparse │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ └── sqlparse.go │ │ └── wrapfs │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ └── modtimefs.go │ ├── liyue201 │ │ └── goqr │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── decoding.go │ │ │ ├── define.go │ │ │ ├── errors.go │ │ │ ├── qr_const.go │ │ │ ├── qrcode.go │ │ │ ├── recognition.go │ │ │ ├── recognizer.go │ │ │ ├── utils.go │ │ │ └── version_db.go │ ├── magefile │ │ └── mage │ │ │ ├── LICENSE │ │ │ ├── mg │ │ │ ├── color.go │ │ │ ├── color_string.go │ │ │ ├── deps.go │ │ │ ├── errors.go │ │ │ ├── fn.go │ │ │ └── runtime.go │ │ │ └── sh │ │ │ ├── cmd.go │ │ │ └── helpers.go │ ├── mattn │ │ └── go-sqlite3 │ │ │ ├── .codecov.yml │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── backup.go │ │ │ ├── callback.go │ │ │ ├── convert.go │ │ │ ├── doc.go │ │ │ ├── error.go │ │ │ ├── sqlite3-binding.c │ │ │ ├── sqlite3-binding.h │ │ │ ├── sqlite3.go │ │ │ ├── sqlite3_context.go │ │ │ ├── sqlite3_func_crypt.go │ │ │ ├── sqlite3_go18.go │ │ │ ├── sqlite3_libsqlite3.go │ │ │ ├── sqlite3_load_extension.go │ │ │ ├── sqlite3_load_extension_omit.go │ │ │ ├── sqlite3_opt_allow_uri_authority.go │ │ │ ├── sqlite3_opt_app_armor.go │ │ │ ├── sqlite3_opt_column_metadata.go │ │ │ ├── sqlite3_opt_foreign_keys.go │ │ │ ├── sqlite3_opt_fts5.go │ │ │ ├── sqlite3_opt_icu.go │ │ │ ├── sqlite3_opt_introspect.go │ │ │ ├── sqlite3_opt_math_functions.go │ │ │ ├── sqlite3_opt_os_trace.go │ │ │ ├── sqlite3_opt_preupdate.go │ │ │ ├── sqlite3_opt_preupdate_hook.go │ │ │ ├── sqlite3_opt_preupdate_omit.go │ │ │ ├── sqlite3_opt_secure_delete.go │ │ │ ├── sqlite3_opt_secure_delete_fast.go │ │ │ ├── sqlite3_opt_serialize.go │ │ │ ├── sqlite3_opt_serialize_omit.go │ │ │ ├── sqlite3_opt_stat4.go │ │ │ ├── sqlite3_opt_unlock_notify.c │ │ │ ├── sqlite3_opt_unlock_notify.go │ │ │ ├── sqlite3_opt_userauth.go │ │ │ ├── sqlite3_opt_userauth_omit.go │ │ │ ├── sqlite3_opt_vacuum_full.go │ │ │ ├── sqlite3_opt_vacuum_incr.go │ │ │ ├── sqlite3_opt_vtable.go │ │ │ ├── sqlite3_other.go │ │ │ ├── sqlite3_solaris.go │ │ │ ├── sqlite3_trace.go │ │ │ ├── sqlite3_type.go │ │ │ ├── sqlite3_usleep_windows.go │ │ │ ├── sqlite3_windows.go │ │ │ ├── sqlite3ext.h │ │ │ └── static_mock.go │ ├── maxbrunsfeld │ │ └── counterfeiter │ │ │ └── v6 │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── appveyor.yml │ │ │ ├── arguments │ │ │ ├── files.go │ │ │ ├── parser.go │ │ │ └── usage.go │ │ │ ├── command │ │ │ └── runner.go │ │ │ ├── generator │ │ │ ├── cache.go │ │ │ ├── ctx.go │ │ │ ├── ctx_old.go │ │ │ ├── fake.go │ │ │ ├── file_reader.go │ │ │ ├── function_loader.go │ │ │ ├── function_template.go │ │ │ ├── import.go │ │ │ ├── interface_loader.go │ │ │ ├── interface_template.go │ │ │ ├── loader.go │ │ │ ├── package_loader.go │ │ │ ├── package_template.go │ │ │ ├── param.go │ │ │ └── return.go │ │ │ └── main.go │ ├── pborman │ │ └── uuid │ │ │ ├── .travis.yml │ │ │ ├── CONTRIBUTING.md │ │ │ ├── CONTRIBUTORS │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── dce.go │ │ │ ├── doc.go │ │ │ ├── hash.go │ │ │ ├── marshal.go │ │ │ ├── node.go │ │ │ ├── sql.go │ │ │ ├── time.go │ │ │ ├── util.go │ │ │ ├── uuid.go │ │ │ ├── version1.go │ │ │ └── version4.go │ ├── skip2 │ │ └── go-qrcode │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── bitset │ │ │ └── bitset.go │ │ │ ├── encoder.go │ │ │ ├── qrcode.go │ │ │ ├── reedsolomon │ │ │ ├── gf2_8.go │ │ │ ├── gf_poly.go │ │ │ └── reed_solomon.go │ │ │ ├── regular_symbol.go │ │ │ ├── symbol.go │ │ │ └── version.go │ ├── spf13 │ │ └── afero │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ ├── afero.go │ │ │ ├── appveyor.yml │ │ │ ├── basepath.go │ │ │ ├── cacheOnReadFs.go │ │ │ ├── const_bsds.go │ │ │ ├── const_win_unix.go │ │ │ ├── copyOnWriteFs.go │ │ │ ├── httpFs.go │ │ │ ├── iofs.go │ │ │ ├── ioutil.go │ │ │ ├── lstater.go │ │ │ ├── match.go │ │ │ ├── mem │ │ │ ├── dir.go │ │ │ ├── dirmap.go │ │ │ └── file.go │ │ │ ├── memmap.go │ │ │ ├── os.go │ │ │ ├── path.go │ │ │ ├── readonlyfs.go │ │ │ ├── regexpfs.go │ │ │ ├── symlink.go │ │ │ ├── unionFile.go │ │ │ └── util.go │ ├── terminalstatic │ │ └── go-xsd-validate │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── errors.go │ │ │ ├── libxml2.go │ │ │ ├── validate_xsd.go │ │ │ └── workspace.code-workspace │ └── wtolson │ │ └── go-taglib │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── README.md │ │ ├── taglib.go │ │ └── test.mp3 ├── golang.org │ └── x │ │ ├── crypto │ │ ├── LICENSE │ │ ├── PATENTS │ │ └── ed25519 │ │ │ └── ed25519.go │ │ ├── image │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── bmp │ │ │ ├── reader.go │ │ │ └── writer.go │ │ ├── ccitt │ │ │ ├── reader.go │ │ │ ├── table.go │ │ │ └── writer.go │ │ ├── draw │ │ │ ├── draw.go │ │ │ ├── impl.go │ │ │ └── scale.go │ │ ├── math │ │ │ └── f64 │ │ │ │ └── f64.go │ │ ├── riff │ │ │ └── riff.go │ │ ├── tiff │ │ │ ├── buffer.go │ │ │ ├── compress.go │ │ │ ├── consts.go │ │ │ ├── fuzz.go │ │ │ ├── lzw │ │ │ │ └── reader.go │ │ │ ├── reader.go │ │ │ └── writer.go │ │ ├── vp8 │ │ │ ├── decode.go │ │ │ ├── filter.go │ │ │ ├── idct.go │ │ │ ├── partition.go │ │ │ ├── pred.go │ │ │ ├── predfunc.go │ │ │ ├── quant.go │ │ │ ├── reconstruct.go │ │ │ └── token.go │ │ ├── vp8l │ │ │ ├── decode.go │ │ │ ├── huffman.go │ │ │ └── transform.go │ │ └── webp │ │ │ ├── decode.go │ │ │ └── doc.go │ │ ├── mod │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── internal │ │ │ └── lazyregexp │ │ │ │ └── lazyre.go │ │ ├── module │ │ │ ├── module.go │ │ │ └── pseudo.go │ │ └── semver │ │ │ └── semver.go │ │ ├── sync │ │ ├── LICENSE │ │ ├── PATENTS │ │ └── errgroup │ │ │ └── errgroup.go │ │ ├── text │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── transform │ │ │ └── transform.go │ │ └── unicode │ │ │ └── norm │ │ │ ├── composition.go │ │ │ ├── forminfo.go │ │ │ ├── input.go │ │ │ ├── iter.go │ │ │ ├── normalize.go │ │ │ ├── readwriter.go │ │ │ ├── tables10.0.0.go │ │ │ ├── tables11.0.0.go │ │ │ ├── tables12.0.0.go │ │ │ ├── tables13.0.0.go │ │ │ ├── tables15.0.0.go │ │ │ ├── tables9.0.0.go │ │ │ ├── transform.go │ │ │ └── trie.go │ │ ├── tools │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── go │ │ │ ├── ast │ │ │ │ └── astutil │ │ │ │ │ ├── enclosing.go │ │ │ │ │ ├── imports.go │ │ │ │ │ ├── rewrite.go │ │ │ │ │ └── util.go │ │ │ ├── gcexportdata │ │ │ │ ├── gcexportdata.go │ │ │ │ └── importer.go │ │ │ ├── internal │ │ │ │ └── packagesdriver │ │ │ │ │ └── sizes.go │ │ │ ├── packages │ │ │ │ ├── doc.go │ │ │ │ ├── external.go │ │ │ │ ├── golist.go │ │ │ │ ├── golist_overlay.go │ │ │ │ ├── loadmode_string.go │ │ │ │ ├── packages.go │ │ │ │ └── visit.go │ │ │ └── types │ │ │ │ ├── objectpath │ │ │ │ └── objectpath.go │ │ │ │ └── typeutil │ │ │ │ ├── callee.go │ │ │ │ ├── imports.go │ │ │ │ ├── map.go │ │ │ │ ├── methodsetcache.go │ │ │ │ └── ui.go │ │ ├── imports │ │ │ └── forward.go │ │ └── internal │ │ │ ├── aliases │ │ │ ├── aliases.go │ │ │ ├── aliases_go121.go │ │ │ └── aliases_go122.go │ │ │ ├── event │ │ │ ├── core │ │ │ │ ├── event.go │ │ │ │ ├── export.go │ │ │ │ └── fast.go │ │ │ ├── doc.go │ │ │ ├── event.go │ │ │ ├── keys │ │ │ │ ├── keys.go │ │ │ │ ├── standard.go │ │ │ │ └── util.go │ │ │ └── label │ │ │ │ └── label.go │ │ │ ├── gcimporter │ │ │ ├── bimport.go │ │ │ ├── exportdata.go │ │ │ ├── gcimporter.go │ │ │ ├── iexport.go │ │ │ ├── iimport.go │ │ │ ├── newInterface10.go │ │ │ ├── newInterface11.go │ │ │ ├── support_go118.go │ │ │ ├── unified_no.go │ │ │ ├── unified_yes.go │ │ │ └── ureader_yes.go │ │ │ ├── gocommand │ │ │ ├── invoke.go │ │ │ ├── vendor.go │ │ │ └── version.go │ │ │ ├── gopathwalk │ │ │ └── walk.go │ │ │ ├── imports │ │ │ ├── fix.go │ │ │ ├── imports.go │ │ │ ├── mod.go │ │ │ ├── mod_cache.go │ │ │ └── sortimports.go │ │ │ ├── packagesinternal │ │ │ └── packages.go │ │ │ ├── pkgbits │ │ │ ├── codes.go │ │ │ ├── decoder.go │ │ │ ├── doc.go │ │ │ ├── encoder.go │ │ │ ├── flags.go │ │ │ ├── frames_go1.go │ │ │ ├── frames_go17.go │ │ │ ├── reloc.go │ │ │ ├── support.go │ │ │ ├── sync.go │ │ │ └── syncmarker_string.go │ │ │ ├── stdlib │ │ │ ├── manifest.go │ │ │ └── stdlib.go │ │ │ ├── tokeninternal │ │ │ └── tokeninternal.go │ │ │ ├── typeparams │ │ │ ├── common.go │ │ │ ├── coretype.go │ │ │ ├── free.go │ │ │ ├── normalize.go │ │ │ ├── termlist.go │ │ │ └── typeterm.go │ │ │ ├── typesinternal │ │ │ ├── errorcode.go │ │ │ ├── errorcode_string.go │ │ │ ├── recv.go │ │ │ ├── toonew.go │ │ │ └── types.go │ │ │ └── versions │ │ │ ├── features.go │ │ │ ├── gover.go │ │ │ ├── toolchain.go │ │ │ ├── toolchain_go119.go │ │ │ ├── toolchain_go120.go │ │ │ ├── toolchain_go121.go │ │ │ ├── types.go │ │ │ ├── types_go121.go │ │ │ ├── types_go122.go │ │ │ └── versions.go │ │ └── xerrors │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── README │ │ ├── adaptor.go │ │ ├── codereview.cfg │ │ ├── doc.go │ │ ├── errors.go │ │ ├── fmt.go │ │ ├── format.go │ │ ├── frame.go │ │ ├── internal │ │ └── internal.go │ │ └── wrap.go ├── gopkg.in │ ├── gorp.v1 │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── dialect.go │ │ ├── errors.go │ │ ├── gorp.go │ │ └── test_all.sh │ └── mineo │ │ └── gocaa.v1 │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── client.go │ │ ├── errors.go │ │ ├── imagesizes.go │ │ ├── reexports.go │ │ └── types.go └── modules.txt └── watch.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /.github/workflows/docker-images.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Publish Docker image 7 | 8 | on: 9 | release: 10 | types: [published] 11 | 12 | jobs: 13 | push_to_registry: 14 | name: Push Docker image to Docker Hub 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Check out the repo 18 | uses: actions/checkout@v2 19 | 20 | - name: Log in to Docker Hub 21 | uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 22 | with: 23 | username: ${{ secrets.DOCKER_USERNAME }} 24 | password: ${{ secrets.DOCKER_PASSWORD }} 25 | 26 | - name: Extract metadata (tags, labels) for Docker 27 | id: meta 28 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 29 | with: 30 | images: ironsmile/euterpe 31 | 32 | - name: Build and push Docker image 33 | uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc 34 | with: 35 | context: . 36 | push: true 37 | tags: ${{ steps.meta.outputs.tags }} 38 | labels: ${{ steps.meta.outputs.labels }} 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | # Sublime project stuff 25 | *.sublime-project 26 | *.sublime-workspace 27 | 28 | # Application logfiles 29 | logfile 30 | 31 | # CTags 32 | .tags 33 | .tags_sorted_by_file 34 | 35 | # Build dir 36 | dist/* 37 | 38 | # The built binary 39 | /httpms 40 | /euterpe 41 | 42 | # OSX bullshits 43 | **/.DS_Store 44 | 45 | # Artifacts from test coverage 46 | /covprofile 47 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.24-alpine3.21 as builder 2 | 3 | RUN apk add --update taglib-dev libc-dev icu-dev icu-data-full upx bmake gcc git zlib-dev 4 | 5 | COPY . /src/euterpe 6 | WORKDIR /src/euterpe 7 | 8 | RUN bmake release 9 | RUN mv euterpe /tmp/euterpe 10 | RUN /tmp/euterpe -config-gen && sed -i 's/localhost:9996/0.0.0.0:9996/' /root/.euterpe/config.json 11 | 12 | FROM alpine:3.21 13 | 14 | RUN apk add --update taglib icu icu-data-full 15 | 16 | COPY --from=builder /tmp/euterpe /usr/local/bin/euterpe 17 | COPY --from=builder /root/.euterpe/config.json /root/.euterpe/config.json 18 | 19 | ENV HOME /root 20 | WORKDIR /root 21 | EXPOSE 9996 22 | CMD ["euterpe"] 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Build a normal binary for development. 2 | all: 3 | go build \ 4 | --tags "sqlite_icu" \ 5 | -ldflags "-X github.com/ironsmile/euterpe/src/version.Version=`git describe --tags --always`" 6 | 7 | # Build a release binary which could be used in the distribution archive. 8 | release: 9 | go build \ 10 | --tags "sqlite_icu" \ 11 | -ldflags "-X github.com/ironsmile/euterpe/src/version.Version=`git describe --tags --always`" \ 12 | -o euterpe 13 | 14 | # Compress it somewhat. It seems that the Euterpe binary gets more than 3 times smaller 15 | # using upx. 16 | upx euterpe 17 | 18 | # Install in $GOPATH/bin. 19 | install: 20 | go install \ 21 | --tags "sqlite_icu" \ 22 | -ldflags "-X github.com/ironsmile/euterpe/src/version.Version=`git describe --tags --always`" 23 | 24 | # Build distribution archive. 25 | dist-archive: 26 | ./tools/build 27 | 28 | # Start euterpe after building it from source. 29 | run: 30 | go run --tags "sqlite_icu" main.go -D -local-fs 31 | -------------------------------------------------------------------------------- /config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "listen": ":443", 3 | 4 | "ssl": true, 5 | 6 | "ssl_certificate": { 7 | "crt": "/full/path/to/certificate/file.crt", 8 | "key": "/full/path/to/key/file.key" 9 | }, 10 | 11 | "basic_authenticate": true, 12 | 13 | "authentication": { 14 | "user": "example", 15 | "password": "example" 16 | }, 17 | 18 | "libraries": [ 19 | "/path/to/my/files", 20 | "/some/more/files/can/be/found/here" 21 | ], 22 | 23 | "library_scan": { 24 | "files_per_operation": 1500, 25 | "sleep_after_operation": "15ms", 26 | "initial_wait_duration": "1s" 27 | }, 28 | 29 | "download_artwork": true, 30 | "discogs_auth_token": "personal-discogs-token-value" 31 | } 32 | -------------------------------------------------------------------------------- /http_root/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #FFFFFF 9 | 10 | 11 | -------------------------------------------------------------------------------- /http_root/favicon/favicon-114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-114.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-120.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-144.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-150.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-152.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-16.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-160.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-180.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-192.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-310.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-32.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-57.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-60.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-64.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-70.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-72.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-76.png -------------------------------------------------------------------------------- /http_root/favicon/favicon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon-96.png -------------------------------------------------------------------------------- /http_root/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/favicon/favicon.ico -------------------------------------------------------------------------------- /http_root/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /http_root/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /http_root/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /http_root/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /http_root/images/unknownAlbum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/images/unknownAlbum.png -------------------------------------------------------------------------------- /http_root/images/unknownArtist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/images/unknownArtist.png -------------------------------------------------------------------------------- /http_root/js/Jplayer.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/js/Jplayer.swf -------------------------------------------------------------------------------- /http_root/skin/blue.monday/jplayer.blue.monday.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/skin/blue.monday/jplayer.blue.monday.jpg -------------------------------------------------------------------------------- /http_root/skin/blue.monday/jplayer.blue.monday.seeking.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/skin/blue.monday/jplayer.blue.monday.seeking.gif -------------------------------------------------------------------------------- /http_root/skin/blue.monday/jplayer.blue.monday.video.play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/http_root/skin/blue.monday/jplayer.blue.monday.video.play.png -------------------------------------------------------------------------------- /http_root/squash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(dirname `readlink -f $0`) 4 | 5 | cat js/jquery.min.js js/jquery.jplayer.min.js js/add-on/jplayer.playlist.min.js \ 6 | js/bootstrap.min.js js/app.js js/URI.min.js > js/squashed.js 7 | 8 | cat css/bootstrap.min.css css/screen.css > css/squashed.css 9 | -------------------------------------------------------------------------------- /images/barded-spice-install-step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/images/barded-spice-install-step1.png -------------------------------------------------------------------------------- /images/barded-spice-install-step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/images/barded-spice-install-step2.png -------------------------------------------------------------------------------- /images/barded-spice-install-step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/images/barded-spice-install-step3.png -------------------------------------------------------------------------------- /images/euterpe-preview.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/images/euterpe-preview.webp -------------------------------------------------------------------------------- /images/heavy-metal-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/images/heavy-metal-128.png -------------------------------------------------------------------------------- /sqls/library_schema.sql: -------------------------------------------------------------------------------- 1 | create table `albums` ( 2 | `id` integer not null primary key, 3 | `name` text, 4 | `fs_path` text 5 | ); 6 | 7 | create table `artists` ( 8 | `id` integer not null primary key, 9 | `name` text 10 | ); 11 | 12 | create table `tracks` ( 13 | `id` integer not null primary key, 14 | `album_id` integer, 15 | `artist_id` integer, 16 | `name` text, 17 | `number` integer, 18 | `fs_path` text 19 | ); 20 | 21 | create index tracks_ids on `tracks` (`id`); 22 | create index tracks_paths on `tracks` (`fs_path`); 23 | create index albums_ids on `albums` (`id`); 24 | create index artists_ids on `artists` (`id`); 25 | -------------------------------------------------------------------------------- /sqls/migrations/001_album_artworks.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | 3 | create table `albums_artworks` ( 4 | `id` integer not null primary key, 5 | `album_id` integer unique, 6 | `artwork_cover` blob default null, 7 | `updated_at` integer 8 | ); 9 | 10 | create index albums_artwork_album_ids on `albums_artworks` (`album_id`); 11 | 12 | -- +migrate Down 13 | 14 | drop table `albums_artworks`; 15 | -------------------------------------------------------------------------------- /sqls/migrations/002_uniqueness.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | 3 | -- First deal with the `artists` table. An artist is expected to be present 4 | -- only once in the database. So this should be represented in the schema. 5 | create unique index if not exists unique_artist on `artists` ('name'); 6 | 7 | -- Now make sure albums are unique. This means an album in a particular directory 8 | -- since one might have the same album multiple times. Different formats, possibly. 9 | create unique index if not exists unique_albums on `albums` (`name`, `fs_path`); 10 | 11 | -- Next is line is the tracks. A track is uniquely identified by its file location. 12 | -- So make sure it is unique then! 13 | drop index if exists tracks_paths; 14 | create unique index if not exists unique_tracks on `tracks` ('fs_path'); 15 | 16 | -- +migrate Down 17 | 18 | drop index if exists unique_artist; 19 | drop index if exists unique_albums; 20 | drop index if exists unique_tracks; 21 | create index tracks_paths on `tracks` (`fs_path`); 22 | -------------------------------------------------------------------------------- /sqls/migrations/003_track_duration.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | alter table tracks add column duration integer; 3 | 4 | -- +migrate Down 5 | alter table tracks drop column duration; 6 | -------------------------------------------------------------------------------- /sqls/migrations/004_artists_images.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | 3 | create table `artists_images` ( 4 | `id` integer not null primary key, 5 | `artist_id` integer unique, 6 | `image` blob default null, 7 | `updated_at` integer 8 | ); 9 | 10 | create index artists_images_artist_ids on `artists_images` (`artist_id`); 11 | 12 | -- +migrate Down 13 | 14 | drop table `artists_images`; 15 | -------------------------------------------------------------------------------- /sqls/migrations/005_small_images.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | alter table `artists_images` add column `image_small` blob default null; 3 | alter table `albums_artworks` add column `artwork_cover_small` blob default null; 4 | 5 | -- +migrate Down 6 | alter table `artists_images` drop column `image_small`; 7 | alter table `albums_artworks` drop column `artwork_cover_small`; 8 | -------------------------------------------------------------------------------- /sqls/migrations/006_stats.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | create table if not exists `user_stats` ( 3 | `track_id` integer, 4 | `favourite` integer null, -- Unix timestamp at which it was starred 5 | `user_rating` integer null, 6 | `last_played` integer null, -- Unix timestamp in seconds. 7 | `play_count` integer not null default 0, 8 | FOREIGN KEY(track_id) REFERENCES tracks(id) ON UPDATE CASCADE ON DELETE CASCADE 9 | ); 10 | 11 | create unique index if not exists `unique_user_stats` on `user_stats` (`track_id`); 12 | 13 | -- +migrate Down 14 | drop index if exists `unique_user_stats`; 15 | drop table if exists `user_stats`; 16 | -------------------------------------------------------------------------------- /sqls/migrations/007_album_artist_stats.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | create table if not exists `albums_stats` ( 3 | `album_id` integer, 4 | `favourite` integer null, -- Unix timestamp at which it was starred 5 | `user_rating` integer null, -- Value in the 1-5 range 6 | FOREIGN KEY(album_id) REFERENCES albums(id) ON UPDATE CASCADE ON DELETE CASCADE 7 | ); 8 | 9 | create unique index if not exists `unique_album_stats` on `albums_stats` (`album_id`); 10 | 11 | create table if not exists `artists_stats` ( 12 | `artist_id` integer, 13 | `favourite` integer null, -- Unix timestamp at which it was starred 14 | `user_rating` integer null, -- Value in the 1-5 range 15 | FOREIGN KEY(artist_id) REFERENCES artists(id) ON UPDATE CASCADE ON DELETE CASCADE 16 | ); 17 | 18 | create unique index if not exists `unique_artists_stats` on `artists_stats` (`artist_id`); 19 | 20 | -- +migrate Down 21 | drop index if exists `unique_album_stats`; 22 | drop table if exists `albums_stats`; 23 | 24 | drop index if exists `unique_artists_stats`; 25 | drop table if exists `artists_stats`; 26 | -------------------------------------------------------------------------------- /sqls/migrations/008_more_track_columns.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | alter table tracks add column year integer null; -- four digit number 3 | alter table tracks add column bitrate integer null; -- bits per second 4 | alter table tracks add column size integer null; -- file size in bytes 5 | alter table tracks add column created_at integer null; -- unix timestamp 6 | 7 | -- +migrate Down 8 | alter table tracks drop column created_at; 9 | alter table tracks drop column size; 10 | alter table tracks drop column bitrate; 11 | alter table tracks drop column year; 12 | -------------------------------------------------------------------------------- /sqls/migrations/009_internet_radio.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | CREATE TABLE IF NOT EXISTS `radio_stations` ( 3 | `id` integer not null primary key, 4 | `name` text not null, 5 | `stream_url` text not null, 6 | `home_page` text null 7 | ); 8 | 9 | -- +migrate Down 10 | drop table if exists `radio_stations`; 11 | -------------------------------------------------------------------------------- /sqls/migrations/010_playlists.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | CREATE TABLE IF NOT EXISTS `playlists` ( 3 | `id` integer not null primary key, 4 | `name` text not null, 5 | `description` text null, 6 | `public` integer default 1, 7 | `created_at` integer not null, 8 | `updated_at` integer not null 9 | ); 10 | 11 | CREATE TABLE IF NOT EXISTS `playlists_tracks` ( 12 | `playlist_id` integer not null, 13 | `track_id` integer not null, 14 | `index` integer not null default 0, 15 | FOREIGN KEY(playlist_id) REFERENCES playlists(id) ON UPDATE CASCADE ON DELETE CASCADE, 16 | FOREIGN KEY(track_id) REFERENCES tracks(id) ON UPDATE CASCADE ON DELETE CASCADE 17 | ); 18 | 19 | CREATE TABLE IF NOT EXISTS `playlists_images` ( 20 | `playlist_id` integer unique not null, 21 | `image` blob not null, 22 | `updated_at` integer not null, 23 | FOREIGN KEY(playlist_id) REFERENCES playlists(id) ON UPDATE CASCADE ON DELETE CASCADE 24 | ); 25 | 26 | create unique index if not exists playlist_pairs on `playlists_tracks` ('playlist_id', `track_id`); 27 | 28 | -- +migrate Down 29 | drop table if exists `playlists`; 30 | drop table if exists `playlists_tracks`; 31 | drop table if exists `playlists_images`; 32 | -------------------------------------------------------------------------------- /sqls/migrations/011_playlists_uniqe_index.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | drop index if exists playlist_pairs; 3 | create unique index if not exists playlist_pairs_with_index on `playlists_tracks` ('playlist_id', `index`); 4 | 5 | -- +migrate Down 6 | drop index if exists playlist_pairs_with_index; 7 | create unique index if not exists playlist_pairs on `playlists_tracks` ('playlist_id', `track_id`); 8 | -------------------------------------------------------------------------------- /src/art/caa_client.go: -------------------------------------------------------------------------------- 1 | package art 2 | 3 | import ( 4 | "github.com/pborman/uuid" 5 | cca "gopkg.in/mineo/gocaa.v1" 6 | ) 7 | 8 | //counterfeiter:generate . CAAClient 9 | 10 | // CAAClient represents a Cover Art Archive client for getting a release front 11 | // image. 12 | type CAAClient interface { 13 | GetReleaseFront(mbid uuid.UUID, size int) (image cca.CoverArtImage, err error) 14 | } 15 | -------------------------------------------------------------------------------- /src/art/client_test_helpers.go: -------------------------------------------------------------------------------- 1 | package art 2 | 3 | // SetCAAClient sets the underlying CAAClient which will be used by the Client. Only 4 | // useful for tests. 5 | func (c *Client) SetCAAClient(caac CAAClient) { 6 | c.caaClient = caac 7 | } 8 | 9 | // SetMusicBrainzAPIURL sets the MusicBrainz API URL. Only useful for tests. 10 | func (c *Client) SetMusicBrainzAPIURL(apiURL string) { 11 | c.musicBrainzAPIHost = apiURL 12 | } 13 | 14 | // SetDiscogsAPIURL sets the Discogs API URL. Only useful for tests. 15 | func (c *Client) SetDiscogsAPIURL(apiURL string) { 16 | c.discogsAPIHost = apiURL 17 | } 18 | -------------------------------------------------------------------------------- /src/art/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package art is responsible for getting cover art for albums or artist images over the 3 | internet. 4 | 5 | It finds album artwork by first querying the MusicBrainz web service for a releaseID using 6 | the artist name and album name. Then using this ID it queries the Cover Art Archive 7 | for the corresponding album front art. 8 | 9 | Artist images are found using the MusicBrainz database and Discogs. 10 | 11 | The following APIs are used to achieve this packages' objective: 12 | 13 | * MusicBrainz API: https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2 14 | * Cover Art Archive: https://musicbrainz.org/doc/Cover_Art_Archive/ 15 | * Discogs API: https://www.discogs.com/developers/ 16 | */ 17 | package art 18 | -------------------------------------------------------------------------------- /src/art/generate.go: -------------------------------------------------------------------------------- 1 | package art 2 | 3 | // This file is here just to hold generate directives and to prevent them 4 | // being copied on more than one place throughout the package files. 5 | 6 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 7 | -------------------------------------------------------------------------------- /src/assert/common.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import "fmt" 4 | 5 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 6 | 7 | //counterfeiter:generate . TestingFatalf 8 | 9 | // TestingFatalf is an which supports reporting fatal errors in testing types such as 10 | // testing.T, testing.TB and similar. 11 | type TestingFatalf interface { 12 | Fatalf(format string, args ...any) 13 | Helper() 14 | } 15 | 16 | func fromMsgAndArgs(msgAndArgs ...any) string { 17 | if len(msgAndArgs) == 0 { 18 | return "" 19 | } 20 | 21 | fmtStr, ok := msgAndArgs[0].(string) 22 | if !ok { 23 | panic("The first argument in msgAndArgs must be a string format value.") 24 | } 25 | 26 | return fmt.Sprintf(" ("+fmtStr+")", msgAndArgs[1:]...) 27 | } 28 | -------------------------------------------------------------------------------- /src/assert/equal.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Equal checks whether expected and actual are actually equal and fails the test 4 | // if they are not. 5 | func Equal[V comparable](t TestingFatalf, expected, actual V, msgAndArgs ...any) { 6 | t.Helper() 7 | 8 | if expected == actual { 9 | return 10 | } 11 | 12 | t.Fatalf("not equal: expected `%#v` but got `%#v`%s", 13 | expected, actual, fromMsgAndArgs(msgAndArgs...), 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/assert/nils.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // NilErr checks that `val` is nil. Causes a fatal error otherwise. 4 | func NilErr(t TestingFatalf, val error, msgAndArgs ...any) { 5 | t.Helper() 6 | 7 | if val == nil { 8 | return 9 | } 10 | 11 | t.Fatalf("expected nil but got `%s`%s", val, fromMsgAndArgs(msgAndArgs...)) 12 | } 13 | 14 | // NotNilErr checks that `val` is not nil. Causes a fatal error otherwise. 15 | func NotNilErr(t TestingFatalf, val error, msgAndArgs ...any) { 16 | t.Helper() 17 | 18 | if val != nil { 19 | return 20 | } 21 | 22 | t.Fatalf("unexpected nil%s", fromMsgAndArgs(msgAndArgs...)) 23 | } 24 | -------------------------------------------------------------------------------- /src/assert/nils_test.go: -------------------------------------------------------------------------------- 1 | package assert_test 2 | 3 | import ( 4 | "io" 5 | "testing" 6 | 7 | "github.com/ironsmile/euterpe/src/assert" 8 | "github.com/ironsmile/euterpe/src/assert/assertfakes" 9 | ) 10 | 11 | // TestNilErr makes sure that ErrNil works as expected. 12 | func TestNilErr(t *testing.T) { 13 | var nilErr error 14 | 15 | fakeTf := &assertfakes.FakeTestingFatalf{} 16 | assert.NilErr(fakeTf, nilErr) 17 | if fakeTf.FatalfCallCount() != 0 { 18 | t.Fatalf("unexpected Fatalf() call for nil error") 19 | } 20 | if fakeTf.HelperCallCount() != 1 { 21 | t.Fatalf("testing.T.Helper() not called") 22 | } 23 | 24 | assert.NilErr(fakeTf, io.EOF) 25 | if fakeTf.FatalfCallCount() != 1 { 26 | t.Fatalf("expected Fatalf() to be called but it was not") 27 | } 28 | } 29 | 30 | // TestNotNilErr makes sure that ErrNotNil works as expected. 31 | func TestNotNilErr(t *testing.T) { 32 | 33 | fakeTf := &assertfakes.FakeTestingFatalf{} 34 | assert.NotNilErr(fakeTf, io.EOF) 35 | if fakeTf.FatalfCallCount() != 0 { 36 | t.Fatalf("unexpected Fatalf() call for nil error") 37 | } 38 | if fakeTf.HelperCallCount() != 1 { 39 | t.Fatalf("testing.T.Helper() not called") 40 | } 41 | 42 | var nilErr error 43 | assert.NotNilErr(fakeTf, nilErr) 44 | if fakeTf.FatalfCallCount() != 1 { 45 | t.Fatalf("expected Fatalf() to be called but it was not") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/daemon/daemon_nix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package daemon 4 | 5 | import "syscall" 6 | 7 | // StopSignals contains all the signals which will make our daemon remove its pidfile 8 | var StopSignals = []syscall.Signal{ 9 | syscall.SIGINT, 10 | syscall.SIGKILL, 11 | syscall.SIGTERM, 12 | } 13 | -------------------------------------------------------------------------------- /src/daemon/daemon_test.go: -------------------------------------------------------------------------------- 1 | package daemon 2 | 3 | import "testing" 4 | 5 | func TestDaemonizing(t *testing.T) { 6 | //!TODO: figure out how to do that in the first place! :D 7 | } 8 | -------------------------------------------------------------------------------- /src/daemon/daemon_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package daemon 4 | 5 | import "os" 6 | 7 | var StopSignals []os.Signal = []os.Signal{ 8 | os.Interrupt, 9 | os.Kill, 10 | } 11 | -------------------------------------------------------------------------------- /src/daemon/doc.go: -------------------------------------------------------------------------------- 1 | // Package daemon contains utilities aimed to helping with the long-term 2 | // running of the application. 3 | package daemon 4 | -------------------------------------------------------------------------------- /src/helpers/helpers_nix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | /* 4 | Helpers for all non-windows machines 5 | */ 6 | 7 | package helpers 8 | 9 | const ( 10 | // euterpeDir is the name of the Euterpe directory in the user's home directory. 11 | euterpeDir = ".euterpe" 12 | 13 | // httpmsDir was a directory where the Euterpe files were stored before its 14 | // rename from HTTPMS. Now it is kept for backward compatibility. If this 15 | // directory is present then it will be used instead of the one in euterpeDir. 16 | // With the presumption that migration to the new directory hasn't happened yet. 17 | httpmsDir = ".httpms" 18 | ) 19 | -------------------------------------------------------------------------------- /src/helpers/helpers_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | /* 4 | Helpers for windows machines 5 | */ 6 | 7 | package helpers 8 | 9 | const ( 10 | httpmsDir = "httpms" 11 | 12 | euterpeDir = "euterpe" 13 | ) 14 | -------------------------------------------------------------------------------- /src/library/bytes_read_closer.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | import "bytes" 4 | 5 | // bytesReadCloser is a helper type which helps bytes.Reader implement io.ReadCloser. 6 | type bytesReadCloser struct { 7 | bytes.Buffer 8 | } 9 | 10 | // Close is a no-op which is here only to implement io.Closer and io.ReadCloser. 11 | func (b *bytesReadCloser) Close() error { 12 | return nil 13 | } 14 | 15 | func newBytesReadCloser(buff []byte) *bytesReadCloser { 16 | return &bytesReadCloser{ 17 | Buffer: *bytes.NewBuffer(buff), 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/library/format.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | import ( 4 | "path/filepath" 5 | "strings" 6 | ) 7 | 8 | func mediaFormatFromFileName(path string) string { 9 | format := strings.TrimLeft(filepath.Ext(path), ".") 10 | if format == "" { 11 | format = "mp3" 12 | } 13 | return strings.ToLower(format) 14 | } 15 | -------------------------------------------------------------------------------- /src/library/generate.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | 5 | // This file is here just to hold the generate directives so that they are not duplicated 6 | // in many places. 7 | -------------------------------------------------------------------------------- /src/library/local_library_migrate.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | import ( 4 | "fmt" 5 | "io/fs" 6 | "log" 7 | "net/http" 8 | 9 | migrate "github.com/ironsmile/sql-migrate" 10 | ) 11 | 12 | // sqlMigrateDirectory is the directory whithin the `sqlFilesFS` which contains 13 | // the .sql files for sql-migrate. 14 | const sqlMigrateDirectory = "migrations" 15 | 16 | // applyMigrations reads the database migrations dir and applies them to the currently 17 | // open database if it is necessary. 18 | func (lib *LocalLibrary) applyMigrations() error { 19 | migrationFiles, err := fs.Sub(lib.sqlFilesFS, sqlMigrateDirectory) 20 | if err != nil { 21 | return fmt.Errorf("locating migrate dir within sqlFiles fs.FS failed: %w", err) 22 | } 23 | 24 | migrations := &migrate.HttpFileSystemMigrationSource{ 25 | FileSystem: http.FS(migrationFiles), 26 | } 27 | 28 | _, err = migrate.ExecMax(lib.db, "sqlite3", migrations, migrate.Up, 0) 29 | if err == nil { 30 | return nil 31 | } 32 | 33 | if _, ok := err.(*migrate.PlanError); ok { 34 | log.Printf("Error applying database migrations: %s\n", err) 35 | return nil 36 | } 37 | 38 | return fmt.Errorf("executing db migration failed: %w", err) 39 | } 40 | -------------------------------------------------------------------------------- /src/library/mock_media_test.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | import "time" 4 | 5 | // MockMedia is a type used for testing the media insertion methods 6 | type MockMedia struct { 7 | artist string 8 | album string 9 | title string 10 | track int 11 | length time.Duration 12 | year int 13 | bitrate int 14 | } 15 | 16 | // Artist satisfies the MediaFile interface and just returns the object attribute. 17 | func (m *MockMedia) Artist() string { 18 | return m.artist 19 | } 20 | 21 | // Album satisfies the MediaFile interface and just returns the object attribute. 22 | func (m *MockMedia) Album() string { 23 | return m.album 24 | } 25 | 26 | // Title satisfies the MediaFile interface and just returns the object attribute. 27 | func (m *MockMedia) Title() string { 28 | return m.title 29 | } 30 | 31 | // Track satisfies the MediaFile interface and just returns the object attribute. 32 | func (m *MockMedia) Track() int { 33 | return m.track 34 | } 35 | 36 | // Length satisfies the MediaFile interface and just returns the object attribute. 37 | func (m *MockMedia) Length() time.Duration { 38 | return m.length 39 | } 40 | 41 | // Year satisfies the MediaFile interface. Returns the object attribute or a default 42 | // value if one is not set. 43 | func (m *MockMedia) Year() int { 44 | return m.year 45 | } 46 | 47 | // Bitrate satisfies the MediaFile interface. Returns the object attribute or a default 48 | // value if one is not set. 49 | func (m *MockMedia) Bitrate() int { 50 | if m.bitrate == 0 { 51 | return 256 52 | } 53 | return m.bitrate 54 | } 55 | -------------------------------------------------------------------------------- /src/library/os_fs.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | import ( 4 | "io/fs" 5 | "os" 6 | ) 7 | 8 | // osFS is a fs.FS implementation which uses the os package as the underlying file 9 | // opener. 10 | type osFS struct{} 11 | 12 | var _ fs.StatFS = (*osFS)(nil) 13 | 14 | func (osfs *osFS) Open(name string) (fs.File, error) { 15 | return os.Open(name) 16 | } 17 | 18 | func (osfs *osFS) Stat(name string) (fs.FileInfo, error) { 19 | return os.Stat(name) 20 | } 21 | -------------------------------------------------------------------------------- /src/library/os_fs_test.go: -------------------------------------------------------------------------------- 1 | package library 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | "testing" 10 | ) 11 | 12 | // TestOsFSOpen makes sure that the osFS Open function actually uses the OS file system 13 | // to do its work. 14 | func TestOsFSOpen(t *testing.T) { 15 | const tmpFileContents = "some-file-contents" 16 | 17 | osfs := &osFS{} 18 | 19 | _, err := osfs.Open(filepath.FromSlash("does/not/exists/here.png")) 20 | if !os.IsNotExist(err) { 21 | t.Errorf("unexpected error for file which does not exist: `%+v`", err) 22 | } 23 | 24 | tmpFile, err := os.CreateTemp(os.TempDir(), "pattern") 25 | if err != nil { 26 | t.Fatalf("failed to create a temporary file: %s", err) 27 | } 28 | tmpFileName := tmpFile.Name() 29 | defer os.Remove(tmpFileName) 30 | fmt.Fprint(tmpFile, tmpFileContents) 31 | tmpFile.Close() 32 | 33 | fh, err := osfs.Open(tmpFileName) 34 | if err != nil { 35 | t.Fatalf("error opening temporary file with osFS: %s", err) 36 | } 37 | defer fh.Close() 38 | 39 | foundContents, err := io.ReadAll(fh) 40 | if err != nil { 41 | t.Fatalf("error reading temporary file: %s", err) 42 | } 43 | 44 | if !bytes.Equal([]byte(tmpFileContents), foundContents) { 45 | t.Errorf("expected file `%s` but got `%s`", tmpFileContents, foundContents) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/playlists/generate.go: -------------------------------------------------------------------------------- 1 | package playlists 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | 5 | // This file is here just to hold the generate directives so that they are not duplicated 6 | // in many places. 7 | -------------------------------------------------------------------------------- /src/radio/generate.go: -------------------------------------------------------------------------------- 1 | package radio 2 | 3 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 4 | 5 | // This file is here just to hold the generate directives so that they are not duplicated 6 | // in many places. 7 | -------------------------------------------------------------------------------- /src/scaler/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package scaler provides utilities for scaling images. 3 | */ 4 | package scaler 5 | -------------------------------------------------------------------------------- /src/scaler/generate.go: -------------------------------------------------------------------------------- 1 | package scaler 2 | 3 | // This file is here just to hold generate directives and to prevent them 4 | // being copied on more than one place throughout the package files. 5 | 6 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 7 | -------------------------------------------------------------------------------- /src/tools/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | import ( 6 | // Packages are imported anonymously so that they could be considered "used" 7 | // by `go mod`. 8 | _ "github.com/maxbrunsfeld/counterfeiter/v6" 9 | ) 10 | 11 | // This file imports packages that are used when running go generate, or used 12 | // during the development process but not otherwise depended on by built code. 13 | -------------------------------------------------------------------------------- /src/version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package version provides version information and utilities. 3 | */ 4 | package version 5 | 6 | import ( 7 | "fmt" 8 | "io" 9 | "runtime" 10 | ) 11 | 12 | // Version stores the current version of Euterpe. It is set during building. 13 | var Version = "dev-unreleased" 14 | 15 | // Print writes a plain text version information in out. 16 | func Print(out io.Writer) { 17 | fmt.Fprintf(out, "Euterpe Media Server %s\n", Version) 18 | fmt.Fprintf(out, "Build with %s\n", runtime.Version()) 19 | } 20 | -------------------------------------------------------------------------------- /src/version/version_test.go: -------------------------------------------------------------------------------- 1 | package version_test 2 | 3 | import ( 4 | "bytes" 5 | "runtime" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/ironsmile/euterpe/src/version" 10 | ) 11 | 12 | // TestVersionPrinting makes sure some things are always part of the printed version 13 | // string. 14 | func TestVersionPrinting(t *testing.T) { 15 | if version.Version == "" { 16 | t.Fatalf("version.Version cannot be completely empty") 17 | } 18 | 19 | var buff bytes.Buffer 20 | version.Print(&buff) 21 | 22 | if !strings.Contains(buff.String(), version.Version) { 23 | t.Errorf("printed version does not contain the actual version string") 24 | } 25 | 26 | if !strings.Contains(buff.String(), runtime.Version()) { 27 | t.Errorf("printed version does not contain Golang version") 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/webserver/functions_test.go: -------------------------------------------------------------------------------- 1 | package webserver_test 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "strings" 8 | "testing" 9 | 10 | "github.com/ironsmile/euterpe/src/webserver" 11 | ) 12 | 13 | // TestWithInternalError makes sure that Internal Server Error status code is 14 | // set when the underlying handler returns an error and hasn't written anything 15 | // at the output. 16 | func TestWithInternalError(t *testing.T) { 17 | var someError = fmt.Errorf("test-error") 18 | 19 | h := webserver.WithInternalError(func(_ http.ResponseWriter, _ *http.Request) error { 20 | return someError 21 | }) 22 | 23 | req := httptest.NewRequest(http.MethodGet, "/", nil) 24 | resp := httptest.NewRecorder() 25 | 26 | h.ServeHTTP(resp, req) 27 | 28 | statusCode := resp.Result().StatusCode 29 | if statusCode != http.StatusInternalServerError { 30 | t.Errorf("expected status code %d but got %d", 31 | http.StatusInternalServerError, statusCode) 32 | } 33 | 34 | if !strings.Contains(resp.Body.String(), someError.Error()) { 35 | // Make sure the error string is part of the response body. This makes 36 | // debugging any problems much easier. 37 | t.Errorf("response body did not include the error string") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/webserver/handler_about.go: -------------------------------------------------------------------------------- 1 | package webserver 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | 8 | "github.com/ironsmile/euterpe/src/version" 9 | "github.com/ironsmile/euterpe/src/webserver/webutils" 10 | ) 11 | 12 | type aboutHandler struct { 13 | resp aboutResponse 14 | } 15 | 16 | // NewAboutHandler returns the HTTP handler which shows a JSON with information 17 | // about the server. 18 | func NewAboutHandler() http.Handler { 19 | return &aboutHandler{ 20 | resp: aboutResponse{ 21 | ServerVersion: version.Version, 22 | }, 23 | } 24 | } 25 | 26 | func (h *aboutHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 27 | w.Header().Add("Content-Type", "application/json; charset=utf-8") 28 | enc := json.NewEncoder(w) 29 | if err := enc.Encode(h.resp); err != nil { 30 | msg := fmt.Sprintf("Failed to encode JSON response: %s", err) 31 | webutils.JSONError(w, msg, http.StatusInternalServerError) 32 | return 33 | } 34 | } 35 | 36 | type aboutResponse struct { 37 | ServerVersion string `json:"server_version"` 38 | } 39 | -------------------------------------------------------------------------------- /src/webserver/handler_about_test.go: -------------------------------------------------------------------------------- 1 | package webserver_test 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "net/http/httptest" 7 | "strings" 8 | "testing" 9 | 10 | "github.com/ironsmile/euterpe/src/assert" 11 | "github.com/ironsmile/euterpe/src/version" 12 | "github.com/ironsmile/euterpe/src/webserver" 13 | ) 14 | 15 | // TestAboutHandler makes sure that the /v1/about HTTP handler returns the information 16 | // promised in the API contract. 17 | func TestAboutHandler(t *testing.T) { 18 | aboutHandler := webserver.NewAboutHandler() 19 | 20 | req := httptest.NewRequest(http.MethodGet, "/v1/about", nil) 21 | resp := httptest.NewRecorder() 22 | 23 | aboutHandler.ServeHTTP(resp, req) 24 | defer resp.Result().Body.Close() 25 | 26 | assert.Equal(t, http.StatusOK, resp.Result().StatusCode) 27 | if !strings.Contains(resp.Result().Header.Get("Content-Type"), "application/json") { 28 | t.Errorf("expected application/json content type") 29 | } 30 | 31 | kvStore := map[string]any{} 32 | dec := json.NewDecoder(resp.Result().Body) 33 | err := dec.Decode(&kvStore) 34 | assert.NilErr(t, err, "decoding JSON response failed") 35 | 36 | val, found := kvStore["server_version"] 37 | if !found { 38 | t.Fatalf("did not find `server_version` in JSON object") 39 | } 40 | 41 | valStr, ok := val.(string) 42 | if !ok { 43 | t.Fatalf("`server_version` was not a string") 44 | } 45 | 46 | assert.Equal(t, version.Version, valStr, "version string mismatch") 47 | } 48 | -------------------------------------------------------------------------------- /src/webserver/handler_logout.go: -------------------------------------------------------------------------------- 1 | package webserver 2 | 3 | import "net/http" 4 | 5 | // NewLogoutHandler returns a handler which will logout the user form his HTTP 6 | // session by unsetting his session cookie. 7 | func NewLogoutHandler() http.Handler { 8 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 9 | cookie := &http.Cookie{ 10 | Name: sessionCookieName, 11 | Value: "", 12 | Path: "/", 13 | HttpOnly: true, 14 | MaxAge: -1, 15 | } 16 | http.SetCookie(w, cookie) 17 | 18 | w.Header().Set("Location", "/login/") 19 | w.WriteHeader(http.StatusFound) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /src/webserver/handler_register_token.go: -------------------------------------------------------------------------------- 1 | package webserver 2 | 3 | import "net/http" 4 | 5 | // NewRigisterTokenHandler returns a handler resposible for checking and eventually 6 | // registering registering in the database token generated to a device. 7 | // !TODO: actually store the device token in the database once it has a unique ID 8 | func NewRigisterTokenHandler() http.Handler { 9 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 10 | w.Header().Set("Content-Type", "application/json") 11 | w.WriteHeader(http.StatusNoContent) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /src/webserver/handler_register_token_test.go: -------------------------------------------------------------------------------- 1 | package webserver_test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | 8 | "github.com/gorilla/mux" 9 | "github.com/ironsmile/euterpe/src/webserver" 10 | ) 11 | 12 | // TestRegisterTokenHandler makes sure that the handler returns well formatted JSON 13 | // and responds with HTTP 204. 14 | func TestRegisterTokenHandler(t *testing.T) { 15 | h := routeRegisterTokenHandler(webserver.NewRigisterTokenHandler()) 16 | 17 | req := httptest.NewRequest(http.MethodPost, "/v1/register/token/", nil) 18 | resp := httptest.NewRecorder() 19 | 20 | h.ServeHTTP(resp, req) 21 | 22 | responseCode := resp.Result().StatusCode 23 | if responseCode != http.StatusNoContent { 24 | t.Errorf( 25 | "expected HTTP response code `%d` but got `%d`", 26 | http.StatusNoContent, 27 | responseCode, 28 | ) 29 | } 30 | } 31 | 32 | // routeRegisterTokenHandler wraps a handler the same way the web server will do when 33 | // constructing the main application router. This is needed for tests so that the 34 | // Gorilla mux variables will be parsed. 35 | func routeRegisterTokenHandler(h http.Handler) http.Handler { 36 | router := mux.NewRouter() 37 | router.StrictSlash(true) 38 | router.UseEncodedPath() 39 | router.Handle(webserver.APIv1EndpointRegisterToken, h).Methods( 40 | webserver.APIv1Methods[webserver.APIv1EndpointRegisterToken]..., 41 | ) 42 | 43 | return router 44 | } 45 | -------------------------------------------------------------------------------- /src/webserver/handler_template.go: -------------------------------------------------------------------------------- 1 | package webserver 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/ironsmile/euterpe/src/version" 10 | ) 11 | 12 | // NewTemplateHandler returns a handler which will execute the page template inside 13 | // the layout template. 14 | func NewTemplateHandler(tpl *template.Template, title string) http.Handler { 15 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 16 | data := struct { 17 | Title string 18 | Version string 19 | Req *http.Request 20 | Menu []menu 21 | }{ 22 | Title: title, 23 | Version: version.Version, 24 | Req: r, 25 | Menu: []menu{ 26 | { 27 | Name: "Player", 28 | URI: "/", 29 | Active: r.URL.Path == "/", 30 | }, 31 | { 32 | Name: "Add Device", 33 | URI: "/add_device/", 34 | Active: r.URL.Path == "/add_device/", 35 | }, 36 | }, 37 | } 38 | if err := tpl.Execute(w, data); err != nil { 39 | errorMessage := fmt.Sprintf("Error executing template: %s.\n", err) 40 | log.Print(errorMessage) 41 | http.Error(w, errorMessage, http.StatusInternalServerError) 42 | } 43 | }) 44 | } 45 | 46 | type menu struct { 47 | URI string 48 | Name string 49 | Active bool 50 | } 51 | -------------------------------------------------------------------------------- /src/webserver/handler_terry.go: -------------------------------------------------------------------------------- 1 | /* 2 | This HTTP handler echoes Terry's name. 3 | 4 | "A man is not dead while his name is still spoken." 5 | 6 | As proposed in in http://www.gnuterrypratchett.com/ 7 | */ 8 | 9 | package webserver 10 | 11 | import ( 12 | "net/http" 13 | ) 14 | 15 | // TerryHandler adds the X-Clacks-Overhead header. It wraps around the actual handler. 16 | type TerryHandler struct { 17 | wrapped http.Handler 18 | } 19 | 20 | // ServeHTTP satisfies the http.Handler interface. 21 | func (th TerryHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) { 22 | writer.Header().Set("X-Clacks-Overhead", "GNU Terry Pratchett") 23 | th.wrapped.ServeHTTP(writer, req) 24 | } 25 | 26 | // NewTerryHandler returns a new TerryHandler, ready for use. 27 | func NewTerryHandler(handler http.Handler) http.Handler { 28 | return &TerryHandler{wrapped: handler} 29 | } 30 | -------------------------------------------------------------------------------- /src/webserver/subsonic/cover_art_interfaces.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import "net/http" 4 | 5 | //counterfeiter:generate . CoverArtHandler 6 | 7 | // CoverArtHandler is an interface which exposes a http.Handler like function for 8 | // serving art images. It uses the database IDs for the albums and artists. 9 | type CoverArtHandler interface { 10 | Find(w http.ResponseWriter, req *http.Request, id int64) error 11 | } 12 | -------------------------------------------------------------------------------- /src/webserver/subsonic/deleteInternetRadioStation.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/ironsmile/euterpe/src/radio" 10 | ) 11 | 12 | func (s *subsonic) deleteInternetRadioStation(w http.ResponseWriter, req *http.Request) { 13 | id := req.Form.Get("id") 14 | if id == "" { 15 | resp := responseError( 16 | errCodeMissingParameter, 17 | "the parameter `id` is required", 18 | ) 19 | encodeResponse(w, req, resp) 20 | return 21 | } 22 | 23 | idInt, err := strconv.ParseInt(id, 10, 64) 24 | if err != nil { 25 | resp := responseError( 26 | errCodeNotFound, 27 | fmt.Sprintf("could not parse radio station ID: %s", err), 28 | ) 29 | encodeResponse(w, req, resp) 30 | return 31 | } 32 | 33 | if err := s.radio.Delete(req.Context(), idInt); errors.Is(err, radio.ErrNotFound) { 34 | resp := responseError( 35 | errCodeNotFound, 36 | "radio station not found", 37 | ) 38 | encodeResponse(w, req, resp) 39 | return 40 | } else if err != nil { 41 | resp := responseError( 42 | errCodeGeneric, 43 | fmt.Sprintf("could not delete radio station: %s", err), 44 | ) 45 | encodeResponse(w, req, resp) 46 | return 47 | } 48 | 49 | encodeResponse(w, req, responseOk()) 50 | } 51 | -------------------------------------------------------------------------------- /src/webserver/subsonic/delete_playlist.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "strconv" 7 | 8 | "github.com/ironsmile/euterpe/src/playlists" 9 | ) 10 | 11 | func (s *subsonic) deletePlaylist(w http.ResponseWriter, req *http.Request) { 12 | id, err := strconv.ParseInt(req.Form.Get("id"), 10, 64) 13 | if err != nil && req.Form.Get("id") == "" { 14 | resp := responseError(errCodeMissingParameter, "playlist ID is missing in query") 15 | encodeResponse(w, req, resp) 16 | return 17 | } else if err != nil { 18 | resp := responseError(errCodeNotFound, "playlist not found") 19 | encodeResponse(w, req, resp) 20 | return 21 | } 22 | 23 | err = s.playlists.Delete(req.Context(), id) 24 | if err != nil && errors.Is(err, playlists.ErrNotFound) { 25 | resp := responseError(errCodeNotFound, "playlist not found") 26 | encodeResponse(w, req, resp) 27 | return 28 | } else if err != nil { 29 | resp := responseError(errCodeGeneric, err.Error()) 30 | encodeResponse(w, req, resp) 31 | return 32 | } 33 | 34 | encodeResponse(w, req, responseOk()) 35 | } 36 | -------------------------------------------------------------------------------- /src/webserver/subsonic/errors.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | type apiErrorCode int 4 | 5 | // Error codes defined in the Subsonic API documentation. 6 | const ( 7 | errCodeGeneric apiErrorCode = 0 8 | errCodeMissingParameter apiErrorCode = 10 9 | errCodeVersionClient apiErrorCode = 20 10 | errCodeVersionServer apiErrorCode = 30 11 | errCodeWrongUserOrPass apiErrorCode = 40 12 | errCodeTokenAuthLDAP apiErrorCode = 41 13 | errCodeNotAuthorized apiErrorCode = 50 14 | errCodeNotFound apiErrorCode = 70 15 | ) 16 | -------------------------------------------------------------------------------- /src/webserver/subsonic/generate.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | // This file is here just to hold generate directives and to prevent them 4 | // being copied on more than one place throughout the package files. 5 | 6 | //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 7 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_album.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | ) 7 | 8 | func (s *subsonic) getAlbum(w http.ResponseWriter, req *http.Request) { 9 | idString := req.Form.Get("id") 10 | subsonicID, err := strconv.ParseInt(idString, 10, 64) 11 | if idString == "" || err != nil || !isAlbumID(subsonicID) { 12 | resp := responseError(errCodeNotFound, "album not found") 13 | encodeResponse(w, req, resp) 14 | return 15 | } 16 | 17 | albumID := toAlbumDBID(subsonicID) 18 | 19 | album, err := s.lib.GetAlbum(req.Context(), albumID) 20 | if err != nil { 21 | resp := responseError(errCodeGeneric, err.Error()) 22 | encodeResponse(w, req, resp) 23 | return 24 | } 25 | 26 | alEntry := xsdAlbumWithSongsID3{ 27 | xsdAlbumID3: dbAlbumToAlbumID3Entry(album), 28 | } 29 | 30 | tracks := s.lib.GetAlbumFiles(req.Context(), albumID) 31 | for _, track := range tracks { 32 | alEntry.Children = append(alEntry.Children, trackToChild( 33 | track, 34 | s.getLastModified(), 35 | )) 36 | } 37 | 38 | resp := albumResponse{ 39 | baseResponse: responseOk(), 40 | Album: alEntry, 41 | } 42 | 43 | encodeResponse(w, req, resp) 44 | } 45 | 46 | type albumResponse struct { 47 | baseResponse 48 | 49 | Album xsdAlbumWithSongsID3 `xml:"album" json:"album"` 50 | } 51 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_album_info.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import "net/http" 4 | 5 | func (s *subsonic) getAlbumInfo(w http.ResponseWriter, req *http.Request) { 6 | s.getAlbumInfo2(w, req) 7 | } 8 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_artist.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | ) 7 | 8 | func (s *subsonic) getArtist(w http.ResponseWriter, req *http.Request) { 9 | idString := req.Form.Get("id") 10 | subsonicID, err := strconv.ParseInt(idString, 10, 64) 11 | if idString == "" || err != nil || !isArtistID(subsonicID) { 12 | resp := responseError(errCodeNotFound, "artist not found") 13 | encodeResponse(w, req, resp) 14 | return 15 | } 16 | 17 | artistID := toArtistDBID(subsonicID) 18 | 19 | entry, err := s.getArtistDirectory(req, artistID) 20 | if err != nil { 21 | resp := responseError(errCodeGeneric, err.Error()) 22 | encodeResponse(w, req, resp) 23 | return 24 | } 25 | 26 | artEtr := xsdArtistWithAlbumsID3{ 27 | xsdArtistID3: directoryToArtistID3(entry), 28 | } 29 | 30 | for _, child := range entry.Children { 31 | artEtr.Children = append(artEtr.Children, toAlbumID3Entry(child)) 32 | } 33 | 34 | resp := artistResponse{ 35 | baseResponse: responseOk(), 36 | Artist: artEtr, 37 | } 38 | 39 | encodeResponse(w, req, resp) 40 | } 41 | 42 | type artistResponse struct { 43 | baseResponse 44 | 45 | Artist xsdArtistWithAlbumsID3 `xml:"artist" json:"artist"` 46 | } 47 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_artist_info.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "strconv" 7 | 8 | "github.com/ironsmile/euterpe/src/library" 9 | ) 10 | 11 | func (s *subsonic) getArtistInfo(w http.ResponseWriter, req *http.Request) { 12 | idString := req.Form.Get("id") 13 | subsonicID, err := strconv.ParseInt(idString, 10, 64) 14 | if idString == "" || err != nil || !isArtistID(subsonicID) { 15 | resp := responseError(errCodeNotFound, "artist not found") 16 | encodeResponse(w, req, resp) 17 | return 18 | } 19 | 20 | artistID := toArtistDBID(subsonicID) 21 | 22 | artist, err := s.lib.GetArtist(req.Context(), artistID) 23 | if errors.Is(err, library.ErrArtistNotFound) { 24 | resp := responseError(errCodeNotFound, "artist not found") 25 | encodeResponse(w, req, resp) 26 | return 27 | } else if err != nil { 28 | resp := responseError(errCodeGeneric, err.Error()) 29 | encodeResponse(w, req, resp) 30 | return 31 | } 32 | 33 | baseArtistInfo := s.getArtistInfoBase(req, artist) 34 | resp := artistInfoResponse{ 35 | baseResponse: baseArtistInfo.baseResponse, 36 | ArtistInfo: baseArtistInfo.ArtistInfo2, 37 | } 38 | 39 | encodeResponse(w, req, resp) 40 | } 41 | 42 | type artistInfoResponse struct { 43 | baseResponse 44 | 45 | // ArtistInfo reuses the aristInfo2Element element since for the moment 46 | // it is exactly the same as what would've been the artistInfoElement. 47 | ArtistInfo xsdArtistInfoBase `xml:"artistInfo"` 48 | } 49 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_genres.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func (s *subsonic) getGenres(w http.ResponseWriter, req *http.Request) { 8 | resp := genresResponse{ 9 | baseResponse: responseOk(), 10 | } 11 | 12 | encodeResponse(w, req, resp) 13 | } 14 | 15 | type genresResponse struct { 16 | baseResponse 17 | 18 | Genres struct{} `xml:"genres" json:"genres"` 19 | } 20 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_internet_radion_stagions.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import "net/http" 4 | 5 | func (s *subsonic) getInternetRadionStations(w http.ResponseWriter, req *http.Request) { 6 | stations, err := s.radio.GetAll(req.Context()) 7 | if err != nil { 8 | resp := responseError(errCodeGeneric, err.Error()) 9 | encodeResponse(w, req, resp) 10 | return 11 | } 12 | 13 | resp := getStationsResponse{ 14 | baseResponse: responseOk(), 15 | } 16 | 17 | for _, station := range stations { 18 | resp.Result.Stations = append(resp.Result.Stations, fromRadioStation(station)) 19 | } 20 | encodeResponse(w, req, resp) 21 | } 22 | 23 | type getStationsResponse struct { 24 | baseResponse 25 | 26 | Result xsdInternetRadioStations `xml:"internetRadioStations" json:"internetRadioStations"` 27 | } 28 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_license.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | func (s *subsonic) getLicense(w http.ResponseWriter, req *http.Request) { 9 | resp := licenseResponse{ 10 | baseResponse: responseOk(), 11 | } 12 | 13 | // Always valid for 10 years into the future. 14 | t := time.Now().Add(365 * 10 * 24 * time.Hour) 15 | 16 | resp.License.Valid = "true" 17 | resp.License.Email = "always-valid@listen-to-euterpe.eu" 18 | resp.License.LicenseExpires = t.Format(time.RFC3339) 19 | 20 | encodeResponse(w, req, resp) 21 | } 22 | 23 | type licenseResponse struct { 24 | baseResponse 25 | 26 | License struct { 27 | Valid string `xml:"valid,attr" json:"valid"` 28 | Email string `xml:"email,attr" json:"email"` 29 | LicenseExpires string `xml:"licenseExpires,attr" json:"licenseExpires"` 30 | } `xml:"license" json:"license"` 31 | } 32 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_music_folders.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func (s *subsonic) getMusicFolders(w http.ResponseWriter, req *http.Request) { 8 | resp := musicFoldersResponse{ 9 | baseResponse: responseOk(), 10 | MusicFolders: musicFolders{ 11 | Children: []musicFolder{ 12 | { 13 | ID: combinedMusicFolderID, 14 | Name: "Combined Music Library", 15 | }, 16 | }, 17 | }, 18 | } 19 | 20 | encodeResponse(w, req, resp) 21 | } 22 | 23 | type musicFoldersResponse struct { 24 | baseResponse 25 | 26 | MusicFolders musicFolders `xml:"musicFolders" json:"musicFolders"` 27 | } 28 | 29 | type musicFolders struct { 30 | Children []musicFolder `xml:"musicFolder" json:"musicFolder"` 31 | } 32 | 33 | type musicFolder struct { 34 | ID int64 `xml:"id,attr" json:"id,string"` 35 | Name string `xml:"name,attr" json:"name"` 36 | } 37 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_open_subsonic_extensions.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import "net/http" 4 | 5 | func (s *subsonic) getOpenSubsonicExtensions(w http.ResponseWriter, req *http.Request) { 6 | resp := osExtensionsResponse{ 7 | baseResponse: responseOk(), 8 | Extensions: []osExtension{ 9 | { 10 | Name: "formPost", 11 | Versions: []int{1}, 12 | }, 13 | }, 14 | } 15 | 16 | encodeResponse(w, req, resp) 17 | } 18 | 19 | type osExtensionsResponse struct { 20 | baseResponse 21 | 22 | Extensions []osExtension `xml:"openSubsonicExtensions" json:"openSubsonicExtensions"` 23 | } 24 | 25 | type osExtension struct { 26 | Name string `xml:"name,attr" json:"name"` 27 | Versions []int `xml:"versions" json:"versions"` 28 | } 29 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_playlist.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/ironsmile/euterpe/src/playlists" 10 | ) 11 | 12 | func (s *subsonic) getPlaylist(w http.ResponseWriter, req *http.Request) { 13 | idString := req.Form.Get("id") 14 | if idString == "" { 15 | resp := responseError(errCodeMissingParameter, "playlist ID is required") 16 | encodeResponse(w, req, resp) 17 | return 18 | } 19 | 20 | playlistID, err := strconv.ParseInt(idString, 10, 64) 21 | if err != nil { 22 | resp := responseError(errCodeNotFound, "playlist not found") 23 | encodeResponse(w, req, resp) 24 | return 25 | } 26 | 27 | playlist, err := s.playlists.Get(req.Context(), playlistID) 28 | if err != nil && errors.Is(err, playlists.ErrNotFound) { 29 | resp := responseError(errCodeNotFound, "playlist not found") 30 | encodeResponse(w, req, resp) 31 | return 32 | } else if err != nil { 33 | resp := responseError( 34 | errCodeGeneric, 35 | fmt.Sprintf("failed to get created playlist: %s", err), 36 | ) 37 | encodeResponse(w, req, resp) 38 | return 39 | } 40 | 41 | resp := playlistWithSongsResponse{ 42 | baseResponse: responseOk(), 43 | Playlist: toXsdPlaylistWithSongs(playlist, s.auth.User, s.lastModified), 44 | } 45 | 46 | encodeResponse(w, req, resp) 47 | } 48 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_playlists.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/ironsmile/euterpe/src/playlists" 7 | ) 8 | 9 | func (s *subsonic) getPlaylists(w http.ResponseWriter, req *http.Request) { 10 | username := req.Form.Get("username") 11 | if username != "" && username != s.auth.User { 12 | resp := responseError(errCodeNotFound, "username not found") 13 | encodeResponse(w, req, resp) 14 | return 15 | } 16 | 17 | playlists, err := s.playlists.List(req.Context(), playlists.ListArgs{ 18 | Offset: 0, 19 | Count: 0, // 0 means "all" 20 | }) 21 | if err != nil { 22 | resp := responseError(errCodeGeneric, err.Error()) 23 | encodeResponse(w, req, resp) 24 | return 25 | } 26 | 27 | resp := playlistsResponse{ 28 | baseResponse: responseOk(), 29 | } 30 | 31 | for _, playlist := range playlists { 32 | resp.Playlists.Children = append( 33 | resp.Playlists.Children, 34 | toXsdPlaylist(playlist, s.auth.User), 35 | ) 36 | } 37 | 38 | encodeResponse(w, req, resp) 39 | } 40 | 41 | type playlistsResponse struct { 42 | baseResponse 43 | 44 | Playlists xsdPlaylists `xml:"playlists" json:"playlists"` 45 | } 46 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_song.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "strconv" 7 | 8 | "github.com/ironsmile/euterpe/src/library" 9 | ) 10 | 11 | func (s *subsonic) getSong(w http.ResponseWriter, req *http.Request) { 12 | idString := req.Form.Get("id") 13 | subsonicID, err := strconv.ParseInt(idString, 10, 64) 14 | if idString == "" || err != nil || !isTrackID(subsonicID) { 15 | resp := responseError(errCodeNotFound, "song not found") 16 | encodeResponse(w, req, resp) 17 | return 18 | } 19 | 20 | trackID := toTrackDBID(subsonicID) 21 | 22 | track, err := s.lib.GetTrack(req.Context(), trackID) 23 | if errors.Is(err, library.ErrNotFound) { 24 | resp := responseError(errCodeNotFound, "song not found") 25 | encodeResponse(w, req, resp) 26 | return 27 | } 28 | 29 | resp := songResponse{ 30 | baseResponse: responseOk(), 31 | Song: trackToChild(track, s.lastModified), 32 | } 33 | 34 | encodeResponse(w, req, resp) 35 | } 36 | 37 | type songResponse struct { 38 | baseResponse 39 | 40 | Song xsdChild `xml:"song" json:"song"` 41 | } 42 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_user.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import "net/http" 4 | 5 | func (s *subsonic) getUser(w http.ResponseWriter, req *http.Request) { 6 | username := req.Form.Get("username") 7 | if username == "" { 8 | resp := responseError(errCodeMissingParameter, "missing username parameter") 9 | encodeResponse(w, req, resp) 10 | return 11 | } 12 | 13 | if username != s.auth.User { 14 | resp := responseError(errCodeNotFound, "user not found") 15 | encodeResponse(w, req, resp) 16 | return 17 | } 18 | 19 | resp := getUserResponse{ 20 | baseResponse: responseOk(), 21 | 22 | User: xsdUser{ 23 | Username: s.auth.User, 24 | Scrobbling: true, 25 | AdminRole: true, 26 | SettingsRole: true, 27 | DownloadRole: true, 28 | UploadRole: true, 29 | PlaylistRole: true, 30 | CoverArtRole: true, 31 | CommentRole: true, 32 | PodcastRole: true, 33 | StreamRole: true, 34 | JukeboxRole: true, 35 | ShareRole: true, 36 | Folders: []int64{ 37 | combinedMusicFolderID, 38 | }, 39 | }, 40 | } 41 | 42 | encodeResponse(w, req, resp) 43 | } 44 | 45 | type getUserResponse struct { 46 | baseResponse 47 | 48 | User xsdUser `xml:"user" json:"user"` 49 | } 50 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_video_info.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func (s *subsonic) getVideoInfo(w http.ResponseWriter, req *http.Request) { 8 | resp := responseError(errCodeNotFound, "video not found") 9 | encodeResponse(w, req, resp) 10 | } 11 | -------------------------------------------------------------------------------- /src/webserver/subsonic/get_videos.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func (s *subsonic) getVideos(w http.ResponseWriter, req *http.Request) { 8 | resp := videosResponse{ 9 | baseResponse: responseOk(), 10 | } 11 | 12 | encodeResponse(w, req, resp) 13 | } 14 | 15 | type videosResponse struct { 16 | baseResponse 17 | 18 | Videos struct{} `xml:"videos" json:"videos"` 19 | } 20 | -------------------------------------------------------------------------------- /src/webserver/subsonic/ping.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func (s *subsonic) apiPing(w http.ResponseWriter, req *http.Request) { 8 | encodeResponse(w, req, pingResponse{ 9 | baseResponse: responseOk(), 10 | }) 11 | } 12 | 13 | type pingResponse struct { 14 | baseResponse 15 | } 16 | -------------------------------------------------------------------------------- /src/webserver/subsonic/stream.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | "strconv" 9 | "time" 10 | ) 11 | 12 | func (s *subsonic) stream(w http.ResponseWriter, req *http.Request) { 13 | idString := req.Form.Get("id") 14 | trackID, err := strconv.ParseInt(idString, 10, 64) 15 | if idString == "" || err != nil || !isTrackID(trackID) { 16 | resp := responseError(errCodeNotFound, "track not found") 17 | encodeResponse(w, req, resp) 18 | return 19 | } 20 | 21 | //!TODO: support maximum bitrate and and transcoding. Once done, a separate 22 | // endpoint must be created for the "/download" endpoint. 23 | 24 | filePath := s.lib.GetFilePath(req.Context(), toTrackDBID(trackID)) 25 | 26 | fh, err := os.Open(filePath) 27 | if err != nil { 28 | http.NotFoundHandler().ServeHTTP(w, req) 29 | return 30 | } 31 | defer fh.Close() 32 | 33 | modTime := time.Time{} 34 | st, err := fh.Stat() 35 | if err == nil { 36 | modTime = st.ModTime() 37 | } 38 | 39 | baseName := filepath.Base(filePath) 40 | 41 | w.Header().Add("Content-Disposition", 42 | fmt.Sprintf("filename=\"%s\"", baseName)) 43 | 44 | http.ServeContent(w, req, baseName, modTime, fh) 45 | } 46 | -------------------------------------------------------------------------------- /src/webserver/subsonic/unstar.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func (s *subsonic) unstar(w http.ResponseWriter, req *http.Request) { 8 | favs, ok := s.parseStarArguments(w, req) 9 | if !ok { 10 | return 11 | } 12 | 13 | if err := s.lib.RemoveFavourite(req.Context(), favs); err != nil { 14 | resp := responseError(errCodeGeneric, err.Error()) 15 | encodeResponse(w, req, resp) 16 | return 17 | } 18 | 19 | encodeResponse(w, req, responseOk()) 20 | } 21 | -------------------------------------------------------------------------------- /src/webserver/subsonic/update_internet_radio_station.go: -------------------------------------------------------------------------------- 1 | package subsonic 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | 9 | "github.com/ironsmile/euterpe/src/radio" 10 | ) 11 | 12 | func (s *subsonic) updateInternetRadioStation(w http.ResponseWriter, req *http.Request) { 13 | station, ok := s.radioStationFromParams(w, req) 14 | if !ok { 15 | // Response has already been written by radioStationFromParams. 16 | return 17 | } 18 | 19 | id := req.Form.Get("id") 20 | if id == "" { 21 | resp := responseError( 22 | errCodeMissingParameter, 23 | "the parameter `id` is required", 24 | ) 25 | encodeResponse(w, req, resp) 26 | return 27 | } 28 | 29 | idInt, err := strconv.ParseInt(id, 10, 64) 30 | if err != nil { 31 | resp := responseError( 32 | errCodeNotFound, 33 | fmt.Sprintf("could not parse radio station ID: %s", err), 34 | ) 35 | encodeResponse(w, req, resp) 36 | return 37 | } 38 | 39 | station.ID = idInt 40 | if err := s.radio.Replace(req.Context(), station); errors.Is(err, radio.ErrNotFound) { 41 | resp := responseError( 42 | errCodeNotFound, 43 | "radio station not found", 44 | ) 45 | encodeResponse(w, req, resp) 46 | return 47 | } else if err != nil { 48 | resp := responseError( 49 | errCodeGeneric, 50 | fmt.Sprintf("could not update radio station: %s", err), 51 | ) 52 | encodeResponse(w, req, resp) 53 | return 54 | } 55 | 56 | encodeResponse(w, req, responseOk()) 57 | } 58 | -------------------------------------------------------------------------------- /src/webserver/webutils/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package webutils contains functions and types commonly used by the HTTP handlers. 3 | */ 4 | package webutils 5 | -------------------------------------------------------------------------------- /src/webserver/webutils/error.go: -------------------------------------------------------------------------------- 1 | package webutils 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | // JSONError writes a JSON object with an error message and sets the HTTP status code. 10 | func JSONError(w http.ResponseWriter, message string, statusCode int) { 11 | w.WriteHeader(statusCode) 12 | resp := jsonErrorMessage{ 13 | Error: message, 14 | } 15 | enc := json.NewEncoder(w) 16 | if err := enc.Encode(&resp); err != nil { 17 | log.Printf("error writing body in browse handler: %s", err) 18 | } 19 | } 20 | 21 | type jsonErrorMessage struct { 22 | Error string `json:"error"` 23 | } 24 | -------------------------------------------------------------------------------- /src/webserver/webutils/error_test.go: -------------------------------------------------------------------------------- 1 | package webutils_test 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "net/http/httptest" 7 | "testing" 8 | 9 | "github.com/ironsmile/euterpe/src/webserver/webutils" 10 | ) 11 | 12 | // TestJSONError makes sure that the JSONError function really encodes the response 13 | // as a valid JSON. 14 | func TestJSONError(t *testing.T) { 15 | rec := httptest.NewRecorder() 16 | errMsg := "some error message for testing" 17 | 18 | webutils.JSONError(rec, errMsg, http.StatusBadGateway) 19 | 20 | res := rec.Result() 21 | defer func() { 22 | res.Body.Close() 23 | }() 24 | 25 | if res.StatusCode != http.StatusBadGateway { 26 | t.Errorf("Expected Bad Gateway status but got %d", res.StatusCode) 27 | } 28 | 29 | var respJSON json.RawMessage 30 | dec := json.NewDecoder(res.Body) 31 | if err := dec.Decode(&respJSON); err != nil { 32 | t.Errorf("Failed decoding the JSON response: %s", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /templates/add_device.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

5 | In your mobile app select "Use Barcode" when logging in and then 6 | scan this barcode. 7 |

8 |
9 |
10 |
11 | Generating... 12 |
13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /templates/unauthorized.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 401 Unauthorized 6 | 7 | 8 |

Authentication required

9 | 10 | 11 | -------------------------------------------------------------------------------- /test_files/http_root/second/static: -------------------------------------------------------------------------------- 1 | Second static file -------------------------------------------------------------------------------- /test_files/http_root/static: -------------------------------------------------------------------------------- 1 | This is a static file -------------------------------------------------------------------------------- /test_files/library/folder_one/not_an_mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/test_files/library/folder_one/not_an_mp3 -------------------------------------------------------------------------------- /test_files/library/folder_one/third_file.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/test_files/library/folder_one/third_file.mp3 -------------------------------------------------------------------------------- /test_files/library/test_file_one.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/test_files/library/test_file_one.mp3 -------------------------------------------------------------------------------- /test_files/library/test_file_two.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/test_files/library/test_file_two.mp3 -------------------------------------------------------------------------------- /test_files/more_mp3s/test_file_added.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/test_files/more_mp3s/test_file_added.mp3 -------------------------------------------------------------------------------- /test_files/ogg_files/vorbis-tags.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/test_files/ogg_files/vorbis-tags.ogg -------------------------------------------------------------------------------- /test_files/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDczCCAlugAwIBAgIJALew3NcLQAVoMA0GCSqGSIb3DQEBBQUAMFAxCzAJBgNV 3 | BAYTAkJHMQ4wDAYDVQQIDAVTb2ZpYTEOMAwGA1UEBwwFU29maWExITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAxMDUyMTQzNDJaFw0yMjA1 5 | MTcyMTQzNDJaMFAxCzAJBgNVBAYTAkJHMQ4wDAYDVQQIDAVTb2ZpYTEOMAwGA1UE 6 | BwwFU29maWExITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIw 7 | DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPHlNxroVMUwl7L9jM9zgTXOWuj 8 | M/LgUcHWpbhvjDy6CQTaBBwZpye55UOj2zncZ8SqfmO2XoEn5+bj/ZMQgLooumy/ 9 | ufttms9tJmZ7DiCKks5kVfyUBCDLcQx2i+pN5RozALriHymhZfWKbfCPWxhFoIlZ 10 | HAPfTVxYctOHJ9dWso/RXOw8x5RmaLmzDAeOkXq/zJVasKTGJYh/uolBlHff0Wtc 11 | 9Rk+xjE7PTxDqvuRilcHteB8DvUun4aO9D7Q6tnEKsrm3WPsneYA87DFU5mmjSSI 12 | ip0HZJ9nC+Jiqt8XbLplyehWuHm/hWjAAByJ5GWBLByIQCT16xkPdJIRBBMCAwEA 13 | AaNQME4wHQYDVR0OBBYEFFp9LymoSZtmz/uNuUeoKCKTjz2BMB8GA1UdIwQYMBaA 14 | FFp9LymoSZtmz/uNuUeoKCKTjz2BMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF 15 | BQADggEBAN3YIysy4vvHdUzZVsIbtkVidA/ntYfVHORlcWKSfC0eDk1MfwWg0yhD 16 | Klmhmwc4Gns/U7YTtq9bCBwaEQ7bZdP3Jg4vNkeo8OnIxZxz3IT203B9Hv8H5k6I 17 | 85vEV/pwHSJLN6oSRIJvo5N1bSFRA5G7oOfIHl53/6dwNe/USJR62niZExLvAuzW 18 | Vv/vpld8hiz7ytkQZIETCokv9UdYU6uTf//AawlfoDFMdK8VJ3AfJqoFdpsekAoY 19 | 88edBHZfPHGET/DS8J7PVRWg6yxhBjdKbM2CjAiJs6GjKW2UOBfxhPJh75ksp2nb 20 | 2U6fUgBDU2N0z73rbllwGFnaOU2+jl4= 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /tools/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 5 | cd .. 6 | 7 | os='unknown' 8 | unamestr=`uname` 9 | if [[ "$unamestr" == 'Linux' ]]; then 10 | os='linux' 11 | elif [[ "$unamestr" == 'FreeBSD' ]]; then 12 | os='freebsd' 13 | elif [[ "$unamestr" == 'Darwin' ]]; then 14 | os='darwin' 15 | fi 16 | 17 | arch="amd64" 18 | version=`git describe --tags --always` 19 | 20 | if [[ $# -gt 0 ]]; then 21 | export GOOS="$1" 22 | os="$GOOS" 23 | fi 24 | 25 | if [ -d dist/euterpe ] 26 | then 27 | echo "Removing old dist/euterpe directory..." 28 | rm -rf dist/euterpe 29 | fi 30 | 31 | echo "Making dist directory..." 32 | mkdir -p dist/euterpe 33 | 34 | echo "Building binaries..." 35 | make release 36 | mv euterpe dist/euterpe/euterpe 37 | 38 | for file in README.md 39 | do 40 | echo "Copying $file..." 41 | cp "$file" dist/euterpe 42 | done 43 | 44 | echo "Copying install/uninstall scripts..." 45 | cp tools/install dist/euterpe 46 | cp tools/uninstall dist/euterpe 47 | 48 | archive="euterpe_${version}_${os}_${arch}.tar.gz" 49 | 50 | echo "Creating archive..." 51 | cd dist 52 | tar cfzv "$archive" euterpe 53 | 54 | echo "dist/$archive created" 55 | 56 | echo "Cleaning up..." 57 | cd - 58 | rm -rf dist/euterpe || exit 59 | 60 | echo "Done" 61 | -------------------------------------------------------------------------------- /tools/cross-compile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Still work in progress. 4 | 5 | CGO_ENABLED=1 \ 6 | CC=x86_64-w64-mingw32-gcc-win32 \ 7 | PKG_CONFIG=x86_64-w64-mingw32-pkg-config \ 8 | PKG_CONFIG_PATH=/home/iron4o/taglib/lib/pkgconfig/ \ 9 | ./build windows 10 | 11 | # removing --tags "sqlite_icu" makes the sqlite compile! 12 | -------------------------------------------------------------------------------- /tools/euterpe.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Euterpe Streaming Media Server 3 | ConditionFileIsExecutable=/usr/bin/euterpe 4 | Documentation=https://listen-to-euterpe.eu/docs/ 5 | After=network.target 6 | 7 | [Service] 8 | Type=simple 9 | ExecStart=/usr/bin/euterpe 10 | Restart=on-failure 11 | User=$USER 12 | Group=$GROUP 13 | WorkingDirectory=/home/$USER/.euterpe 14 | StandardOutput=journal 15 | StandardError=journal 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | Alias=httpms 20 | -------------------------------------------------------------------------------- /tools/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | INSTALL_DIR=$(dirname `readlink -f $0`) 3 | cd "$INSTALL_DIR" 4 | cd .. 5 | 6 | if [ -d /etc/euterpe ]; then 7 | echo "Euterpe is already installed. Aborting." 8 | exit 0 9 | fi 10 | 11 | for binary in euterpe 12 | do 13 | if [ -f "/usr/bin/${binary}" ]; then 14 | echo "Euterpe is already installed. Aborting." 15 | exit 0 16 | fi 17 | done 18 | 19 | echo "Installing euterpe dir to /etc/..." 20 | cp -a "$INSTALL_DIR" /etc/euterpe || exit 1 21 | 22 | echo "Setting directory permissions..." 23 | find /etc/euterpe -type d -exec chmod 755 "{}" \; || exit 1 24 | 25 | echo "Moving binaries to /usr/bin/..." 26 | mv /etc/euterpe/euterpe /usr/bin/euterpe || exit 1 27 | 28 | echo "Done" 29 | -------------------------------------------------------------------------------- /tools/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 443 ssl http2; 3 | server_name music.example.com; 4 | 5 | ssl_certificate /etc/certs/music.example.com/fullchain.pem; 6 | ssl_certificate_key /etc/certs/music.example.com/privkey.pem; 7 | include /etc/nginx/ssl-params.conf; 8 | 9 | location / { 10 | proxy_pass http://127.0.0.1:9996; 11 | 12 | proxy_set_header X-Real-IP $remote_addr; 13 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 14 | proxy_set_header X-Forwarded-Proto https; 15 | proxy_set_header X-Forwarded-Port 443; 16 | proxy_set_header Host $host; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tools/uninstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -d /etc/euterpe ]; then 4 | echo "Euterpe is not installed. Aborting." 5 | exit 0 6 | fi 7 | 8 | rm -rf /etc/euterpe 9 | rm /usr/bin/euterpe 10 | -------------------------------------------------------------------------------- /vendor/github.com/dhowden/tag/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*.go] 8 | indent_style = tab 9 | indent_size = 3 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*] 15 | # We recommend you to keep these unchanged 16 | end_of_line = lf 17 | charset = utf-8 18 | trim_trailing_whitespace = true 19 | insert_final_newline = true 20 | -------------------------------------------------------------------------------- /vendor/github.com/dhowden/tag/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7 5 | - tip -------------------------------------------------------------------------------- /vendor/github.com/dhowden/tag/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015, David Howden 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = false 6 | indent_size = 2 7 | indent_style = space 8 | 9 | [{README.md,*.go,Makefile}] 10 | indent_style = tab 11 | 12 | [{README.md,*.go,COMMIT_EDITMSG}] 13 | tab_width = 8 14 | 15 | [Makefile] 16 | indent_size = 4 17 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | *.out 3 | .bin/ 4 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Gabriel Sanches 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/algorithm.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | // Load all hashing functions needed. 5 | _ "crypto/sha256" 6 | _ "crypto/sha512" 7 | ) 8 | 9 | // Algorithm is an algorithm for both signing and verifying a JWT. 10 | type Algorithm interface { 11 | Name() string 12 | Sign(headerPayload []byte) ([]byte, error) 13 | Size() int 14 | Verify(headerPayload, sig []byte) error 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/audience.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import "encoding/json" 4 | 5 | // Audience is a special claim that may either be 6 | // a single string or an array of strings, as per the RFC 7519. 7 | type Audience []string 8 | 9 | // MarshalJSON implements a marshaling function for "aud" claim. 10 | func (a Audience) MarshalJSON() ([]byte, error) { 11 | switch len(a) { 12 | case 0: 13 | return json.Marshal("") // nil or empty slice returns an empty string 14 | case 1: 15 | return json.Marshal(a[0]) 16 | default: 17 | return json.Marshal([]string(a)) 18 | } 19 | } 20 | 21 | // UnmarshalJSON implements an unmarshaling function for "aud" claim. 22 | func (a *Audience) UnmarshalJSON(b []byte) error { 23 | var ( 24 | v interface{} 25 | err error 26 | ) 27 | if err = json.Unmarshal(b, &v); err != nil { 28 | return err 29 | } 30 | switch vv := v.(type) { 31 | case string: 32 | aud := make(Audience, 1) 33 | aud[0] = vv 34 | *a = aud 35 | case []interface{}: 36 | aud := make(Audience, len(vv)) 37 | for i := range vv { 38 | aud[i] = vv[i].(string) 39 | } 40 | *a = aud 41 | } 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/doc.go: -------------------------------------------------------------------------------- 1 | // Package jwt is a JSON Web Token signer, verifier and validator. 2 | package jwt 3 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/hash_pool.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "hash" 5 | "sync" 6 | ) 7 | 8 | type hashPool struct { 9 | *sync.Pool 10 | } 11 | 12 | func newHashPool(hfunc func() hash.Hash) *hashPool { 13 | return &hashPool{&sync.Pool{New: func() interface{} { return hfunc() }}} 14 | } 15 | 16 | func (hp *hashPool) sign(headerPayload []byte) ([]byte, error) { 17 | hh := hp.Pool.Get().(hash.Hash) 18 | defer func() { 19 | hh.Reset() 20 | hp.Pool.Put(hh) 21 | }() 22 | 23 | if _, err := hh.Write(headerPayload); err != nil { 24 | return nil, err 25 | } 26 | return hh.Sum(nil), nil 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/header.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | // Header is a JOSE header narrowed down to the JWT specification from RFC 7519. 4 | // 5 | // Parameters are ordered according to the RFC 7515. 6 | type Header struct { 7 | Algorithm string `json:"alg,omitempty"` 8 | ContentType string `json:"cty,omitempty"` 9 | KeyID string `json:"kid,omitempty"` 10 | Type string `json:"typ,omitempty"` 11 | } 12 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/internal/decode.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/json" 6 | ) 7 | 8 | // Decode decodes a Base64 encoded JSON object using the proper encoding for JWTs. 9 | func Decode(enc []byte, v interface{}) error { 10 | dec, err := DecodeToBytes(enc) 11 | if err != nil { 12 | return err 13 | } 14 | return json.Unmarshal(dec, v) 15 | } 16 | 17 | // DecodeToBytes decodes a Base64 string using the proper encoding for JWTs. 18 | func DecodeToBytes(enc []byte) ([]byte, error) { 19 | encoding := base64.RawURLEncoding 20 | dec := make([]byte, encoding.DecodedLen(len(enc))) 21 | if _, err := encoding.Decode(dec, enc); err != nil { 22 | return nil, err 23 | } 24 | return dec, nil 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/internal/ed25519.go: -------------------------------------------------------------------------------- 1 | // +build go1.13 2 | 3 | package internal 4 | 5 | import ( 6 | "crypto/ed25519" 7 | "crypto/rand" 8 | ) 9 | 10 | // GenerateEd25519Keys generates a pair of keys for testing purposes. 11 | func GenerateEd25519Keys() (ed25519.PrivateKey, ed25519.PublicKey) { 12 | pub, priv, err := ed25519.GenerateKey(rand.Reader) 13 | if err != nil { 14 | panic(err) 15 | } 16 | return priv, pub 17 | } 18 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/internal/ed25519_go1_12.go: -------------------------------------------------------------------------------- 1 | // +build !go1.13 2 | 3 | package internal 4 | 5 | import ( 6 | "crypto/rand" 7 | 8 | "golang.org/x/crypto/ed25519" 9 | ) 10 | 11 | // GenerateEd25519Keys generates a pair of keys for testing purposes. 12 | func GenerateEd25519Keys() (ed25519.PrivateKey, ed25519.PublicKey) { 13 | pub, priv, err := ed25519.GenerateKey(rand.Reader) 14 | if err != nil { 15 | panic(err) 16 | } 17 | return priv, pub 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/internal/epoch.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "time" 4 | 5 | // Epoch is 01/01/1970. 6 | var Epoch = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC) 7 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/internal/errors.go: -------------------------------------------------------------------------------- 1 | // +build go1.13 2 | 3 | package internal 4 | 5 | import ( 6 | "errors" 7 | "fmt" 8 | ) 9 | 10 | // Errorf wraps fmt.Errorf. 11 | func Errorf(format string, a ...interface{}) error { return fmt.Errorf(format, a...) } 12 | 13 | // ErrorAs wraps errors.As. 14 | func ErrorAs(err error, target interface{}) bool { return errors.As(err, target) } 15 | 16 | // ErrorIs wraps errors.Is. 17 | func ErrorIs(err, target error) bool { return errors.Is(err, target) } 18 | 19 | // NewError wraps errors.New. 20 | func NewError(text string) error { return errors.New(text) } 21 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/internal/errors_go1_12.go: -------------------------------------------------------------------------------- 1 | // +build !go1.13 2 | 3 | package internal 4 | 5 | import "golang.org/x/xerrors" 6 | 7 | // Errorf wraps xerrors.Errorf. 8 | func Errorf(format string, a ...interface{}) error { return xerrors.Errorf(format, a...) } 9 | 10 | // ErrorAs wraps xerrors.As. 11 | func ErrorAs(err error, target interface{}) bool { return xerrors.As(err, target) } 12 | 13 | // ErrorIs wraps xerrors.Is. 14 | func ErrorIs(err, target error) bool { return xerrors.Is(err, target) } 15 | 16 | // NewError wraps xerrors.New. 17 | func NewError(text string) error { return xerrors.New(text) } 18 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/json.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | ) 7 | 8 | // ErrNotJSONObject is the error for when a JWT payload is not a JSON object. 9 | var ErrNotJSONObject = errors.New("jwt: payload is not a valid JSON object") 10 | 11 | func isJSONObject(payload []byte) bool { 12 | payload = bytes.TrimSpace(payload) 13 | return payload[0] == '{' && payload[len(payload)-1] == '}' 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/none.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | var _ Algorithm = none{} 4 | 5 | type none struct{} 6 | 7 | // None returns a dull, unsecured algorithm. 8 | func None() Algorithm { return none{} } 9 | 10 | // Name always returns "none". 11 | func (none) Name() string { return "none" } 12 | 13 | // Sign always returns a nil byte slice and a nil error. 14 | func (none) Sign(_ []byte) ([]byte, error) { return nil, nil } 15 | 16 | // Size always returns 0 and a nil error. 17 | func (none) Size() int { return 0 } 18 | 19 | // Verify always returns a nil error. 20 | func (none) Verify(_, _ []byte) error { return nil } 21 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/payload.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | // Payload is a JWT payload according to the RFC 7519. 4 | type Payload struct { 5 | Issuer string `json:"iss,omitempty"` 6 | Subject string `json:"sub,omitempty"` 7 | Audience Audience `json:"aud,omitempty"` 8 | ExpirationTime *Time `json:"exp,omitempty"` 9 | NotBefore *Time `json:"nbf,omitempty"` 10 | IssuedAt *Time `json:"iat,omitempty"` 11 | JWTID string `json:"jti,omitempty"` 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/resolver.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | // Resolver is an Algorithm that needs to set some variables 4 | // based on a Header before performing signing and verification. 5 | type Resolver interface { 6 | Resolve(Header) error 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/gbrlsnchs/jwt/v3/time.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "encoding/json" 5 | "time" 6 | 7 | "github.com/gbrlsnchs/jwt/v3/internal" 8 | ) 9 | 10 | // Time is the allowed format for time, as per the RFC 7519. 11 | type Time struct { 12 | time.Time 13 | } 14 | 15 | // NumericDate is a resolved Unix time. 16 | func NumericDate(tt time.Time) *Time { 17 | if tt.Before(internal.Epoch) { 18 | tt = internal.Epoch 19 | } 20 | return &Time{time.Unix(tt.Unix(), 0)} // set time using Unix time 21 | } 22 | 23 | // MarshalJSON implements a marshaling function for time-related claims. 24 | func (t Time) MarshalJSON() ([]byte, error) { 25 | if t.Before(internal.Epoch) { 26 | return json.Marshal(0) 27 | } 28 | return json.Marshal(t.Unix()) 29 | } 30 | 31 | // UnmarshalJSON implements an unmarshaling function for time-related claims. 32 | func (t *Time) UnmarshalJSON(b []byte) error { 33 | var unix *int64 34 | if err := json.Unmarshal(b, &unix); err != nil { 35 | return err 36 | } 37 | if unix == nil { 38 | return nil 39 | } 40 | tt := time.Unix(*unix, 0) 41 | if tt.Before(internal.Epoch) { 42 | tt = internal.Epoch 43 | } 44 | t.Time = tt 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: 1.7 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/README.md: -------------------------------------------------------------------------------- 1 | context 2 | ======= 3 | [![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) 4 | 5 | gorilla/context is a general purpose registry for global request variables. 6 | 7 | > Note: gorilla/context, having been born well before `context.Context` existed, does not play well 8 | > with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`. 9 | 10 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context 11 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.5.x 7 | - go: 1.6.x 8 | - go: 1.7.x 9 | - go: 1.8.x 10 | - go: 1.9.x 11 | - go: 1.10.x 12 | - go: tip 13 | allow_failures: 14 | - go: tip 15 | 16 | install: 17 | - # Skip 18 | 19 | script: 20 | - go get -t -v ./... 21 | - diff -u <(echo -n) <(gofmt -d .) 22 | - go tool vet . 23 | - go test -v -race ./... 24 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **What version of Go are you running?** (Paste the output of `go version`) 2 | 3 | 4 | **What version of gorilla/mux are you at?** (Paste the output of `git rev-parse HEAD` inside `$GOPATH/src/github.com/gorilla/mux`) 5 | 6 | 7 | **Describe your problem** (and what you have tried so far) 8 | 9 | 10 | **Paste a minimal, runnable, reproduction of your issue below** (use backticks to format it) 11 | 12 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_gorilla.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "net/http" 7 | 8 | "github.com/gorilla/context" 9 | ) 10 | 11 | func contextGet(r *http.Request, key interface{}) interface{} { 12 | return context.Get(r, key) 13 | } 14 | 15 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 16 | if val == nil { 17 | return r 18 | } 19 | 20 | context.Set(r, key, val) 21 | return r 22 | } 23 | 24 | func contextClear(r *http.Request) { 25 | context.Clear(r) 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_native.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "context" 7 | "net/http" 8 | ) 9 | 10 | func contextGet(r *http.Request, key interface{}) interface{} { 11 | return r.Context().Value(key) 12 | } 13 | 14 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 15 | if val == nil { 16 | return r 17 | } 18 | 19 | return r.WithContext(context.WithValue(r.Context(), key, val)) 20 | } 21 | 22 | func contextClear(r *http.Request) { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/test_helpers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package mux 6 | 7 | import "net/http" 8 | 9 | // SetURLVars sets the URL variables for the given request, to be accessed via 10 | // mux.Vars for testing route behaviour. Arguments are not modified, a shallow 11 | // copy is returned. 12 | // 13 | // This API should only be used for testing purposes; it provides a way to 14 | // inject variables into the request context. Alternatively, URL variables 15 | // can be set by making a route that captures the required variables, 16 | // starting a server and sending the request to that server. 17 | func SetURLVars(r *http.Request, val map[string]string) *http.Request { 18 | return setVars(r, val) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/howeyc/fsnotify/.gitignore: -------------------------------------------------------------------------------- 1 | # Setup a Global .gitignore for OS and editor generated files: 2 | # https://help.github.com/articles/ignoring-files 3 | # git config --global core.excludesfile ~/.gitignore_global 4 | 5 | .vagrant 6 | -------------------------------------------------------------------------------- /vendor/github.com/howeyc/fsnotify/AUTHORS: -------------------------------------------------------------------------------- 1 | # Names should be added to this file as 2 | # Name or Organization 3 | # The email address is not required for organizations. 4 | 5 | # You can update this list using the following command: 6 | # 7 | # $ git shortlog -se | awk '{print $2 " " $3 " " $4}' 8 | 9 | # Please keep the list sorted. 10 | 11 | Adrien Bustany 12 | Caleb Spare 13 | Case Nelson 14 | Chris Howey 15 | Christoffer Buchholz 16 | Dave Cheney 17 | Francisco Souza 18 | John C Barstow 19 | Kelvin Fo 20 | Nathan Youngman 21 | Paul Hammond 22 | Pursuit92 23 | Rob Figueiredo 24 | Travis Cline 25 | Tudor Golubenco 26 | bronze1man 27 | debrando 28 | henrikedwards 29 | -------------------------------------------------------------------------------- /vendor/github.com/howeyc/fsnotify/fsnotify_open_bsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build freebsd openbsd netbsd 6 | 7 | package fsnotify 8 | 9 | import "syscall" 10 | 11 | const open_FLAGS = syscall.O_NONBLOCK | syscall.O_RDONLY 12 | -------------------------------------------------------------------------------- /vendor/github.com/howeyc/fsnotify/fsnotify_open_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin 6 | 7 | package fsnotify 8 | 9 | import "syscall" 10 | 11 | const open_FLAGS = syscall.O_EVTONLY 12 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/sql-migrate/.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | *.test 3 | 4 | /sql-migrate/test.db 5 | /test.db 6 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/sql-migrate/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | sudo: false 4 | 5 | go: 6 | - "1.8" 7 | - "1.9" 8 | - "1.10" 9 | 10 | services: 11 | - mysql 12 | - postgresql 13 | 14 | before_install: 15 | - mysql -e "CREATE DATABASE IF NOT EXISTS test;" -uroot 16 | - mysql -e "CREATE DATABASE IF NOT EXISTS test_env;" -uroot 17 | - psql -c "CREATE DATABASE test;" -U postgres 18 | 19 | install: 20 | - go get -t ./... 21 | - go install ./... 22 | 23 | script: 24 | - go test -v ./... 25 | - bash test-integration/postgres.sh 26 | - bash test-integration/mysql.sh 27 | - bash test-integration/mysql-flag.sh 28 | - bash test-integration/mysql-env.sh 29 | - bash test-integration/sqlite.sh 30 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/sql-migrate/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2014-2017 by Ruben Vermeersch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/sql-migrate/sqlparse/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2014-2017 by Ruben Vermeersch 4 | Copyright (C) 2012-2014 by Liam Staskawicz 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/sql-migrate/sqlparse/README.md: -------------------------------------------------------------------------------- 1 | # SQL migration parser 2 | 3 | Based on the [goose](https://bitbucket.org/liamstask/goose) migration parser. 4 | 5 | ## License 6 | 7 | This library is distributed under the [MIT](LICENSE) license. 8 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/wrapfs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Doychin Atanasov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/wrapfs/README.md: -------------------------------------------------------------------------------- 1 | # WrapFS 2 | 3 | `wrapfs` is a Go module which provides wrappers around `fs.FS`. 4 | 5 | ## ModTimeFS 6 | 7 | This wrapper makes sure calls to [fs.FileInfo.Stat](https://pkg.go.dev/io/fs#FileInfo.Stat) 8 | and [fs.DirEntry.Info](https://pkg.go.dev/io/fs#DirEntry.Info) always return non-zero 9 | [ModTime()](https://pkg.go.dev/io/fs#FileInfo.ModTime). In case the wrapped file or entry 10 | return non-zero modification time it stays unchanged. In case they return a zero 11 | modification time then a static mod time will be used instead. 12 | 13 | Usage: 14 | 15 | ```go 16 | var someFs fs.FS = getFS() 17 | modTimeFS := wrapfs.WithModTime(someFS, time.Now()) 18 | http.FileServer(http.FS(modTimeFS)) 19 | ``` 20 | 21 | This is especially helpful for `embed.FS` file systems when used in conjecture with 22 | `http.FileServer`. When `wrapfs.WithModTime` is used in this case the HTTP server will 23 | be able to handle caches which utilize the "Last-Modified" HTTP headers. 24 | 25 | ## Known Limitations 26 | 27 | If new interfaces are added in `fs` they will not be exposed as implemented by the 28 | wrappers until the library has been patched. 29 | -------------------------------------------------------------------------------- /vendor/github.com/ironsmile/wrapfs/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package wrapfs provides wrappers of the [fs.FS] with additional functionality. 3 | */ 4 | package wrapfs 5 | -------------------------------------------------------------------------------- /vendor/github.com/liyue201/goqr/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | notifications: 4 | email: 5 | recipients: 6 | - liyue201@126.com 7 | on_success: change 8 | on_failure: always 9 | 10 | go: 11 | - 1.12 12 | 13 | install: 14 | - go get github.com/mattn/goveralls 15 | 16 | script: 17 | - go test ./... -v -covermode=count -coverprofile=coverage.out 18 | - $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN 19 | 20 | env: 21 | global: 22 | - GO111MODULE=on 23 | - secure: "aOzEdb/ST82OpO4LqLpwrdRs6GnkmdLJbm3o9+2HmJCyiHkhqPY1bGY1TiYxQLl3GkjFkuVP+3RB+E0p2R/1f4xYkg4cIpPoLm+4xJ7c1NsEGTaWVS8rCNTicqdym7C9kJart6KcAeWWoElFxob3+lTdS6sz4kFaURrVQ/lpbzBESH0B5Rwa35u1WasmHkPxsHJ/2a7Xnknv+SerjgMUDiXUYM5IjUWt2fV2Zq/9blTSReng6+6Lj9EdziZcQfWNJxBK/NDBtpNIpOdY+bZEUDQi7InB3IioKpQeVjMGKSAzqhedqnGbZsaO734Z8VjRjcFRJPuuYMMkMw4hGoplDqqrTa2aFgln54NiNk2R6WIcpPKAFdLEL7rCPx6qRLMRq1EEn6h+lAy5mJ6NIpmJmY/IbDEVH9D4z4YVLJbHhU+yAN4Tk5mwW9N2bLceSNxIRSJcCcDlRiBNba5XLdNb/tHq7PEM2lX1oXp4WzdYgGh08a69OAweY/CRQjiTZrbhmbsZ5qo3UMLA34HTfEVWt8UWeAFry5fhtzeLqQa5h0BPwtFsy9bsdukEL3nAWcWF4HaQ2jh2CNO6OvpzRb8i45qj1QpIvGqy/lJbuO5WswFQaZcKK2nmPa2M4f7+EBGFe3VvmOJcJvAt2ZRYVZalbdTLDKMmMgcdYIL4jzzcSs4=" -------------------------------------------------------------------------------- /vendor/github.com/liyue201/goqr/errors.go: -------------------------------------------------------------------------------- 1 | package goqr 2 | 3 | import "errors" 4 | 5 | // Error definition 6 | var ( 7 | ErrNoQRCode = errors.New("no QR code in image") 8 | ErrInvalidGridSize = errors.New("invalid grid size") 9 | ErrInvalidVersion = errors.New("invalid version") 10 | ErrFormatEcc = errors.New("ecc format error") 11 | ErrDataEcc = errors.New("ecc data error") 12 | ErrUnknownDataType = errors.New("unknown data type") 13 | ErrDataOverflow = errors.New("data overflow") 14 | ErrDataUnderflow = errors.New("data underflow") 15 | ) 16 | -------------------------------------------------------------------------------- /vendor/github.com/liyue201/goqr/qr_const.go: -------------------------------------------------------------------------------- 1 | package goqr 2 | 3 | // Limits on the maximum size of QR-codes and their content 4 | const ( 5 | qrMaxBimap = 3917 6 | qrMaxPayload = 8896 7 | 8 | // QR-code ECC types 9 | qrEccLevelM = 0 10 | qrEccLevelL = 1 11 | qrEccLevelH = 2 12 | qrEccLevelQ = 3 13 | 14 | // QR-code data types 15 | qrDataTypeNumeric = 1 16 | qrDataTypeAlpha = 2 17 | qrDataTypeByte = 4 18 | qrDataTypeKanji = 8 19 | 20 | // Common character encodings 21 | qrEciIos8859_1 = 1 22 | qrEciIbm437 = 2 23 | qrEciIos8859_2 = 4 24 | qrEciIso8859_3 = 5 25 | qrEciIso8859_4 = 6 26 | qrEciIso8859_5 = 7 27 | qrEciIso8859_6 = 8 28 | qrEciIso8859_7 = 9 29 | qrEciIso8859_8 = 10 30 | qrEciIso8859_9 = 11 31 | qrEciWindows874 = 13 32 | qrEciIso8859_13 = 15 33 | qrEciIso8859_15 = 17 34 | qrEciShiftJis = 20 35 | qrEciUtf8 = 26 36 | ) 37 | -------------------------------------------------------------------------------- /vendor/github.com/liyue201/goqr/utils.go: -------------------------------------------------------------------------------- 1 | package goqr 2 | 3 | func lineIntersect(p0, p1, q0, q1, r *point) bool { 4 | // (a, b) is perpendicular to line p 5 | a := -(p1.y - p0.y) 6 | b := p1.x - p0.x 7 | 8 | // (c, d) is perpendicular to line q 9 | c := -(q1.y - q0.y) 10 | d := q1.x - q0.x 11 | 12 | // e and f are dot products of the respective vectors with p and q 13 | e := a*p1.x + b*p1.y 14 | f := c*q1.x + d*q1.y 15 | 16 | // Now we need to solve: 17 | // [a b] [rx] [e] 18 | // [c d] [ry] = [f] 19 | // 20 | // We do this by inverting the matrix and applying it to (e, f): 21 | // [ d -b] [e] [rx] 22 | // 1/det [-c a] [f] = [ry] 23 | // 24 | det := (a * d) - (b * c) 25 | if det == 0 { 26 | return false 27 | } 28 | r.x = (d*e - b*f) / det 29 | r.y = (-c*e + a*f) / det 30 | return true 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/magefile/mage/mg/color_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Color"; DO NOT EDIT. 2 | 3 | package mg 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[Black-0] 12 | _ = x[Red-1] 13 | _ = x[Green-2] 14 | _ = x[Yellow-3] 15 | _ = x[Blue-4] 16 | _ = x[Magenta-5] 17 | _ = x[Cyan-6] 18 | _ = x[White-7] 19 | _ = x[BrightBlack-8] 20 | _ = x[BrightRed-9] 21 | _ = x[BrightGreen-10] 22 | _ = x[BrightYellow-11] 23 | _ = x[BrightBlue-12] 24 | _ = x[BrightMagenta-13] 25 | _ = x[BrightCyan-14] 26 | _ = x[BrightWhite-15] 27 | } 28 | 29 | const _Color_name = "BlackRedGreenYellowBlueMagentaCyanWhiteBrightBlackBrightRedBrightGreenBrightYellowBrightBlueBrightMagentaBrightCyanBrightWhite" 30 | 31 | var _Color_index = [...]uint8{0, 5, 8, 13, 19, 23, 30, 34, 39, 50, 59, 70, 82, 92, 105, 115, 126} 32 | 33 | func (i Color) String() string { 34 | if i < 0 || i >= Color(len(_Color_index)-1) { 35 | return "Color(" + strconv.FormatInt(int64(i), 10) + ")" 36 | } 37 | return _Color_name[_Color_index[i]:_Color_index[i+1]] 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/magefile/mage/mg/errors.go: -------------------------------------------------------------------------------- 1 | package mg 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | type fatalErr struct { 9 | code int 10 | error 11 | } 12 | 13 | func (f fatalErr) ExitStatus() int { 14 | return f.code 15 | } 16 | 17 | type exitStatus interface { 18 | ExitStatus() int 19 | } 20 | 21 | // Fatal returns an error that will cause mage to print out the 22 | // given args and exit with the given exit code. 23 | func Fatal(code int, args ...interface{}) error { 24 | return fatalErr{ 25 | code: code, 26 | error: errors.New(fmt.Sprint(args...)), 27 | } 28 | } 29 | 30 | // Fatalf returns an error that will cause mage to print out the 31 | // given message and exit with the given exit code. 32 | func Fatalf(code int, format string, args ...interface{}) error { 33 | return fatalErr{ 34 | code: code, 35 | error: fmt.Errorf(format, args...), 36 | } 37 | } 38 | 39 | // ExitStatus queries the error for an exit status. If the error is nil, it 40 | // returns 0. If the error does not implement ExitStatus() int, it returns 1. 41 | // Otherwise it retiurns the value from ExitStatus(). 42 | func ExitStatus(err error) int { 43 | if err == nil { 44 | return 0 45 | } 46 | exit, ok := err.(exitStatus) 47 | if !ok { 48 | return 1 49 | } 50 | return exit.ExitStatus() 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/magefile/mage/sh/helpers.go: -------------------------------------------------------------------------------- 1 | package sh 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | ) 8 | 9 | // Rm removes the given file or directory even if non-empty. It will not return 10 | // an error if the target doesn't exist, only if the target cannot be removed. 11 | func Rm(path string) error { 12 | err := os.RemoveAll(path) 13 | if err == nil || os.IsNotExist(err) { 14 | return nil 15 | } 16 | return fmt.Errorf(`failed to remove %s: %v`, path, err) 17 | } 18 | 19 | // Copy robustly copies the source file to the destination, overwriting the destination if necessary. 20 | func Copy(dst string, src string) error { 21 | from, err := os.Open(src) 22 | if err != nil { 23 | return fmt.Errorf(`can't copy %s: %v`, src, err) 24 | } 25 | defer from.Close() 26 | finfo, err := from.Stat() 27 | if err != nil { 28 | return fmt.Errorf(`can't stat %s: %v`, src, err) 29 | } 30 | to, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, finfo.Mode()) 31 | if err != nil { 32 | return fmt.Errorf(`can't copy to %s: %v`, dst, err) 33 | } 34 | defer to.Close() 35 | _, err = io.Copy(to, from) 36 | if err != nil { 37 | return fmt.Errorf(`error copying %s to %s: %v`, src, dst, err) 38 | } 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: off 4 | patch: off 5 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | *.exe 3 | *.dll 4 | *.o 5 | 6 | # VSCode 7 | .vscode 8 | 9 | # Exclude from upgrade 10 | upgrade/*.c 11 | upgrade/*.h 12 | 13 | # Exclude upgrade binary 14 | upgrade/upgrade 15 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Yasuhiro Matsumoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build libsqlite3 7 | // +build libsqlite3 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DUSE_LIBSQLITE3 13 | #cgo linux LDFLAGS: -lsqlite3 14 | #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3 15 | #cgo darwin,amd64 CFLAGS: -I/usr/local/opt/sqlite/include 16 | #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/sqlite/lib -lsqlite3 17 | #cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/sqlite/include 18 | #cgo openbsd LDFLAGS: -lsqlite3 19 | #cgo solaris LDFLAGS: -lsqlite3 20 | #cgo windows LDFLAGS: -lsqlite3 21 | #cgo zos LDFLAGS: -lsqlite3 22 | */ 23 | import "C" 24 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build sqlite_omit_load_extension 7 | // +build sqlite_omit_load_extension 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION 13 | */ 14 | import "C" 15 | import ( 16 | "errors" 17 | ) 18 | 19 | func (c *SQLiteConn) loadExtensions(extensions []string) error { 20 | return errors.New("Extensions have been disabled for static builds") 21 | } 22 | 23 | func (c *SQLiteConn) LoadExtension(lib string, entry string) error { 24 | return errors.New("Extensions have been disabled for static builds") 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_allow_uri_authority 8 | // +build sqlite_allow_uri_authority 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build !windows && sqlite_app_armor 8 | // +build !windows,sqlite_app_armor 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_column_metadata.go: -------------------------------------------------------------------------------- 1 | //go:build sqlite_column_metadata 2 | // +build sqlite_column_metadata 3 | 4 | package sqlite3 5 | 6 | /* 7 | #ifndef USE_LIBSQLITE3 8 | #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA 9 | #include 10 | #else 11 | #include 12 | #endif 13 | */ 14 | import "C" 15 | 16 | // ColumnTableName returns the table that is the origin of a particular result 17 | // column in a SELECT statement. 18 | // 19 | // See https://www.sqlite.org/c3ref/column_database_name.html 20 | func (s *SQLiteStmt) ColumnTableName(n int) string { 21 | return C.GoString(C.sqlite3_column_table_name(s.s, C.int(n))) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_foreign_keys 8 | // +build sqlite_foreign_keys 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build sqlite_fts5 || fts5 7 | // +build sqlite_fts5 fts5 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_FTS5 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build sqlite_icu || icu 7 | // +build sqlite_icu icu 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo LDFLAGS: -licuuc -licui18n 13 | #cgo CFLAGS: -DSQLITE_ENABLE_ICU 14 | #cgo darwin,amd64 CFLAGS: -I/usr/local/opt/icu4c/include 15 | #cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/icu4c/lib 16 | #cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/icu4c/include 17 | #cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/icu4c/lib 18 | #cgo openbsd LDFLAGS: -lsqlite3 19 | */ 20 | import "C" 21 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_introspect 8 | // +build sqlite_introspect 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_math_functions.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build sqlite_math_functions 7 | // +build sqlite_math_functions 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_ENABLE_MATH_FUNCTIONS 13 | #cgo LDFLAGS: -lm 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_os_trace.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build sqlite_os_trace 7 | // +build sqlite_os_trace 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -DSQLITE_FORCE_OS_TRACE=1 13 | #cgo CFLAGS: -DSQLITE_DEBUG_OS_TRACE=1 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 G.J.R. Timmer . 2 | // Copyright (C) 2018 segment.com 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build cgo 8 | // +build cgo 9 | 10 | package sqlite3 11 | 12 | // SQLitePreUpdateData represents all of the data available during a 13 | // pre-update hook call. 14 | type SQLitePreUpdateData struct { 15 | Conn *SQLiteConn 16 | Op int 17 | DatabaseName string 18 | TableName string 19 | OldRowID int64 20 | NewRowID int64 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 G.J.R. Timmer . 2 | // Copyright (C) 2018 segment.com 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build !sqlite_preupdate_hook && cgo 8 | // +build !sqlite_preupdate_hook,cgo 9 | 10 | package sqlite3 11 | 12 | // RegisterPreUpdateHook sets the pre-update hook for a connection. 13 | // 14 | // The callback is passed a SQLitePreUpdateData struct with the data for 15 | // the update, as well as methods for fetching copies of impacted data. 16 | // 17 | // If there is an existing preupdate hook for this connection, it will be 18 | // removed. If callback is nil the existing hook (if any) will be removed 19 | // without creating a new one. 20 | func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) { 21 | // NOOP 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_secure_delete 8 | // +build sqlite_secure_delete 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=1 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_secure_delete_fast 8 | // +build sqlite_secure_delete_fast 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_serialize_omit.go: -------------------------------------------------------------------------------- 1 | //go:build libsqlite3 && !sqlite_serialize 2 | // +build libsqlite3,!sqlite_serialize 3 | 4 | package sqlite3 5 | 6 | import ( 7 | "errors" 8 | ) 9 | 10 | /* 11 | #cgo CFLAGS: -DSQLITE_OMIT_DESERIALIZE 12 | */ 13 | import "C" 14 | 15 | func (c *SQLiteConn) Serialize(schema string) ([]byte, error) { 16 | return nil, errors.New("sqlite3: Serialize requires the sqlite_serialize build tag when using the libsqlite3 build tag") 17 | } 18 | 19 | func (c *SQLiteConn) Deserialize(b []byte, schema string) error { 20 | return errors.New("sqlite3: Deserialize requires the sqlite_serialize build tag when using the libsqlite3 build tag") 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_stat4 8 | // +build sqlite_stat4 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_ENABLE_STAT4 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_vacuum_full 8 | // +build sqlite_vacuum_full 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // Copyright (C) 2018 G.J.R. Timmer . 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file. 6 | 7 | //go:build sqlite_vacuum_incr 8 | // +build sqlite_vacuum_incr 9 | 10 | package sqlite3 11 | 12 | /* 13 | #cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2 14 | #cgo LDFLAGS: -lm 15 | */ 16 | import "C" 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_other.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build !windows 7 | // +build !windows 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -I. 13 | #cgo linux LDFLAGS: -ldl 14 | #cgo linux,ppc LDFLAGS: -lpthread 15 | #cgo linux,ppc64 LDFLAGS: -lpthread 16 | #cgo linux,ppc64le LDFLAGS: -lpthread 17 | */ 18 | import "C" 19 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build solaris 7 | // +build solaris 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -D__EXTENSIONS__=1 13 | #cgo LDFLAGS: -lc 14 | */ 15 | import "C" 16 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 G.J.R. Timmer . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build cgo 7 | // +build cgo 8 | 9 | package sqlite3 10 | 11 | // usleep is a function available on *nix based systems. 12 | // This function is not present in Windows. 13 | // Windows has a sleep function but this works with seconds 14 | // and not with microseconds as usleep. 15 | // 16 | // This code should improve performance on windows because 17 | // without the presence of usleep SQLite waits 1 second. 18 | // 19 | // Source: https://github.com/php/php-src/blob/PHP-5.0/win32/time.c 20 | // License: https://github.com/php/php-src/blob/PHP-5.0/LICENSE 21 | // Details: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa 22 | 23 | /* 24 | #include 25 | 26 | void usleep(__int64 usec) 27 | { 28 | HANDLE timer; 29 | LARGE_INTEGER ft; 30 | 31 | // Convert to 100 nanosecond interval, negative value indicates relative time 32 | ft.QuadPart = -(10*usec); 33 | 34 | timer = CreateWaitableTimer(NULL, TRUE, NULL); 35 | SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); 36 | WaitForSingleObject(timer, INFINITE); 37 | CloseHandle(timer); 38 | } 39 | */ 40 | import "C" 41 | 42 | // EOF 43 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build windows 7 | // +build windows 8 | 9 | package sqlite3 10 | 11 | /* 12 | #cgo CFLAGS: -I. 13 | #cgo CFLAGS: -fno-stack-check 14 | #cgo CFLAGS: -fno-stack-protector 15 | #cgo CFLAGS: -mno-stack-arg-probe 16 | #cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T 17 | */ 18 | import "C" 19 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-sqlite3/static_mock.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 Yasuhiro Matsumoto . 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file. 5 | 6 | //go:build !cgo 7 | // +build !cgo 8 | 9 | package sqlite3 10 | 11 | import ( 12 | "database/sql" 13 | "database/sql/driver" 14 | "errors" 15 | ) 16 | 17 | var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub") 18 | 19 | func init() { 20 | sql.Register("sqlite3", &SQLiteDriver{}) 21 | } 22 | 23 | type ( 24 | SQLiteDriver struct { 25 | Extensions []string 26 | ConnectHook func(*SQLiteConn) error 27 | } 28 | SQLiteConn struct{} 29 | ) 30 | 31 | func (SQLiteDriver) Open(s string) (driver.Conn, error) { return nil, errorMsg } 32 | func (c *SQLiteConn) RegisterAggregator(string, any, bool) error { return errorMsg } 33 | func (c *SQLiteConn) RegisterAuthorizer(func(int, string, string, string) int) {} 34 | func (c *SQLiteConn) RegisterCollation(string, func(string, string) int) error { return errorMsg } 35 | func (c *SQLiteConn) RegisterCommitHook(func() int) {} 36 | func (c *SQLiteConn) RegisterFunc(string, any, bool) error { return errorMsg } 37 | func (c *SQLiteConn) RegisterRollbackHook(func()) {} 38 | func (c *SQLiteConn) RegisterUpdateHook(func(int, string, string, int64)) {} 39 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.iml 25 | .idea 26 | .envrc 27 | 28 | /counterfeiter 29 | integration/testdata/output 30 | *.profile 31 | *.bench 32 | /.vscode 33 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 maxbrunsfeld 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/appveyor.yml: -------------------------------------------------------------------------------- 1 | platform: x64 2 | shallow_clone: true 3 | clone_depth: 10 4 | clone_folder: c:\projects\counterfeiter 5 | image: Visual Studio 2019 6 | stack: go 1.16 7 | 8 | environment: 9 | GOPATH: c:\gopath 10 | COUNTERFEITER_NO_GENERATE_WARNING: true 11 | 12 | before_test: 13 | - go vet ./... 14 | 15 | test_script: 16 | - go install . 17 | - copy scripts\counterfeiter.bat c:\gopath\bin 18 | - set PATH=c:\gopath\bin;c:\go\bin;C:\msys64\mingw64\bin;C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%PATH% 19 | - go version 20 | - go generate ./... 21 | - go build ./... 22 | - go test -race ./... 23 | 24 | build: off 25 | deploy: off 26 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/arguments/files.go: -------------------------------------------------------------------------------- 1 | package arguments 2 | 3 | import "os" 4 | 5 | type Evaler func(string) (string, error) 6 | type Stater func(string) (os.FileInfo, error) 7 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/generator/cache.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import "golang.org/x/tools/go/packages" 4 | 5 | type Cache struct { 6 | packageMap map[string]interface{} 7 | } 8 | 9 | type FakeCache struct{} 10 | 11 | func (c *FakeCache) Load(packagePath string) ([]*packages.Package, bool) { return nil, false } 12 | func (c *FakeCache) Store(packagePath string, packages []*packages.Package) {} 13 | 14 | type Cacher interface { 15 | Load(packagePath string) ([]*packages.Package, bool) 16 | Store(packagePath string, packages []*packages.Package) 17 | } 18 | 19 | func (c *Cache) Load(packagePath string) ([]*packages.Package, bool) { 20 | p, ok := c.packageMap[packagePath] 21 | if !ok { 22 | return nil, false 23 | } 24 | packages, ok := p.([]*packages.Package) 25 | return packages, ok 26 | } 27 | 28 | func (c *Cache) Store(packagePath string, packages []*packages.Package) { 29 | if c.packageMap == nil { 30 | c.packageMap = map[string]interface{}{} 31 | } 32 | c.packageMap[packagePath] = packages 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/generator/ctx.go: -------------------------------------------------------------------------------- 1 | // +build go1.14 2 | 3 | package generator 4 | 5 | import "go/build" 6 | 7 | func getBuildContext(workingDir string) build.Context { 8 | ctx := build.Default 9 | ctx.Dir = workingDir 10 | return ctx 11 | } 12 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/generator/ctx_old.go: -------------------------------------------------------------------------------- 1 | // +build !go1.14 2 | 3 | package generator 4 | 5 | import "go/build" 6 | 7 | func getBuildContext(workingDir string) build.Context { 8 | ctx := build.Default 9 | return ctx 10 | } 11 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/generator/function_loader.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "errors" 5 | "go/types" 6 | ) 7 | 8 | func (f *Fake) loadMethodForFunction() error { 9 | t, ok := f.Target.Type().(*types.Named) 10 | if !ok { 11 | return errors.New("target is not a named type") 12 | } 13 | sig, ok := t.Underlying().(*types.Signature) 14 | if !ok { 15 | return errors.New("target does not have an underlying function signature") 16 | } 17 | f.addTypesForMethod(sig) 18 | f.Function = methodForSignature(sig, f.TargetName, f.Imports) 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/generator/package_loader.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "go/types" 5 | 6 | "golang.org/x/tools/go/packages" 7 | ) 8 | 9 | type rawMethod struct { 10 | Func *types.Func 11 | Signature *types.Signature 12 | } 13 | 14 | // packageMethodSet identifies the functions that are exported from a given 15 | // package. 16 | func packageMethodSet(p *packages.Package) []*rawMethod { 17 | if p == nil || p.Types == nil || p.Types.Scope() == nil { 18 | return nil 19 | } 20 | var result []*rawMethod 21 | scope := p.Types.Scope() 22 | for _, name := range scope.Names() { 23 | obj := scope.Lookup(name) 24 | if !obj.Exported() { 25 | continue // skip unexported names 26 | } 27 | fun, ok := obj.(*types.Func) 28 | if !ok { 29 | continue 30 | } 31 | sig, ok := obj.Type().(*types.Signature) 32 | if !ok { 33 | continue 34 | } 35 | result = append(result, &rawMethod{ 36 | Func: fun, 37 | Signature: sig, 38 | }) 39 | } 40 | 41 | return result 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/maxbrunsfeld/counterfeiter/v6/generator/package_template.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "strings" 5 | "text/template" 6 | ) 7 | 8 | var packageFuncs = template.FuncMap{ 9 | "ToLower": strings.ToLower, 10 | "UnExport": unexport, 11 | "Replace": strings.Replace, 12 | "Generate": func(suffix string) string { return suffix + ":generate" }, // yes, this seems insane but ensures that we can use `go generate ./...` from the main package 13 | } 14 | 15 | const packageTemplate string = `{{.Header}}// Code generated by counterfeiter. DO NOT EDIT. 16 | package {{.DestinationPackage}} 17 | 18 | import ( 19 | {{- range $index, $import := .Imports.ByAlias}} 20 | {{$import}} 21 | {{- end}} 22 | ) 23 | 24 | //{{Generate "go"}} go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 25 | //{{Generate "counterfeiter"}} . {{.Name}} 26 | 27 | // {{.Name}} is a generated interface representing the exported functions 28 | // in the {{.TargetPackage}} package. 29 | type {{.Name}} interface { 30 | {{- range .Methods}} 31 | {{.Name}}({{.Params.AsNamedArgsWithTypes}}) {{.Returns.AsReturnSignature}} 32 | {{- end}} 33 | } 34 | 35 | type {{.Name}}Shim struct {} 36 | 37 | {{- range .Methods}} 38 | func (p *{{$.Name}}Shim) {{.Name}}({{.Params.AsNamedArgsWithTypes}}) {{.Returns.AsReturnSignature}} { 39 | {{if .Returns.HasLength}}return {{end}}{{$.TargetAlias}}.{{.Name}}({{.Params.AsNamedArgsForInvocation}}) 40 | } 41 | {{end}} 42 | var _ {{.Name}} = new({{.Name}}Shim) 43 | ` 44 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4.3 5 | - 1.5.3 6 | - tip 7 | 8 | script: 9 | - go test -v ./... 10 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We definitely welcome patches and contribution to this project! 4 | 5 | ### Legal requirements 6 | 7 | In order to protect both you and ourselves, you will need to sign the 8 | [Contributor License Agreement](https://cla.developers.google.com/clas). 9 | 10 | You may have already signed it for other Google projects. 11 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Paul Borman 2 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/README.md: -------------------------------------------------------------------------------- 1 | This project was automatically exported from code.google.com/p/go-uuid 2 | 3 | # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) 4 | The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. 5 | 6 | ###### Install 7 | `go get github.com/pborman/uuid` 8 | 9 | ###### Documentation 10 | [![GoDoc](https://godoc.org/github.com/pborman/uuid?status.svg)](http://godoc.org/github.com/pborman/uuid) 11 | 12 | Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: 13 | http://godoc.org/github.com/pborman/uuid 14 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // The uuid package generates and inspects UUIDs. 6 | // 7 | // UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. 8 | package uuid 9 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/version1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | ) 10 | 11 | // NewUUID returns a Version 1 UUID based on the current NodeID and clock 12 | // sequence, and the current time. If the NodeID has not been set by SetNodeID 13 | // or SetNodeInterface then it will be set automatically. If the NodeID cannot 14 | // be set NewUUID returns nil. If clock sequence has not been set by 15 | // SetClockSequence then it will be set automatically. If GetTime fails to 16 | // return the current NewUUID returns nil. 17 | func NewUUID() UUID { 18 | if nodeID == nil { 19 | SetNodeInterface("") 20 | } 21 | 22 | now, seq, err := GetTime() 23 | if err != nil { 24 | return nil 25 | } 26 | 27 | uuid := make([]byte, 16) 28 | 29 | time_low := uint32(now & 0xffffffff) 30 | time_mid := uint16((now >> 32) & 0xffff) 31 | time_hi := uint16((now >> 48) & 0x0fff) 32 | time_hi |= 0x1000 // Version 1 33 | 34 | binary.BigEndian.PutUint32(uuid[0:], time_low) 35 | binary.BigEndian.PutUint16(uuid[4:], time_mid) 36 | binary.BigEndian.PutUint16(uuid[6:], time_hi) 37 | binary.BigEndian.PutUint16(uuid[8:], seq) 38 | copy(uuid[10:], nodeID) 39 | 40 | return uuid 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/version4.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | // Random returns a Random (Version 4) UUID or panics. 8 | // 9 | // The strength of the UUIDs is based on the strength of the crypto/rand 10 | // package. 11 | // 12 | // A note about uniqueness derived from from the UUID Wikipedia entry: 13 | // 14 | // Randomly generated UUIDs have 122 random bits. One's annual risk of being 15 | // hit by a meteorite is estimated to be one chance in 17 billion, that 16 | // means the probability is about 0.00000000006 (6 × 10−11), 17 | // equivalent to the odds of creating a few tens of trillions of UUIDs in a 18 | // year and having one duplicate. 19 | func NewRandom() UUID { 20 | uuid := make([]byte, 16) 21 | randomBits([]byte(uuid)) 22 | uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 23 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 24 | return uuid 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/skip2/go-qrcode/.gitignore: -------------------------------------------------------------------------------- 1 | *.sw* 2 | *.png 3 | *.directory 4 | qrcode/qrcode 5 | -------------------------------------------------------------------------------- /vendor/github.com/skip2/go-qrcode/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7 5 | 6 | script: 7 | - go test -v ./... 8 | 9 | -------------------------------------------------------------------------------- /vendor/github.com/skip2/go-qrcode/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Tom Harwood 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/.gitignore: -------------------------------------------------------------------------------- 1 | sftpfs/file1 2 | sftpfs/test/ 3 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | arch: 4 | - amd64 5 | - ppc64e 6 | 7 | go: 8 | - "1.14" 9 | - "1.15" 10 | - "1.16" 11 | - tip 12 | 13 | os: 14 | - linux 15 | - osx 16 | 17 | matrix: 18 | allow_failures: 19 | - go: tip 20 | fast_finish: true 21 | 22 | script: 23 | - go build -v ./... 24 | - go test -count=1 -cover -race -v ./... 25 | - go vet ./... 26 | - FILES=$(gofmt -s -l . zipfs sftpfs mem tarfs); if [[ -n "${FILES}" ]]; then echo "You have go format errors; gofmt your changes"; exit 1; fi 27 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | clone_folder: C:\gopath\src\github.com\spf13\afero 3 | environment: 4 | GOPATH: C:\gopath 5 | build_script: 6 | - cmd: >- 7 | go version 8 | 9 | go env 10 | 11 | go get -v github.com/spf13/afero/... 12 | 13 | go build -v github.com/spf13/afero/... 14 | test_script: 15 | - cmd: go test -count=1 -cover -race -v github.com/spf13/afero/... 16 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/const_bsds.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Steve Francia . 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // +build aix darwin openbsd freebsd netbsd dragonfly 15 | 16 | package afero 17 | 18 | import ( 19 | "syscall" 20 | ) 21 | 22 | const BADFD = syscall.EBADF 23 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/const_win_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 Steve Francia . 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | // +build !darwin 14 | // +build !openbsd 15 | // +build !freebsd 16 | // +build !dragonfly 17 | // +build !netbsd 18 | // +build !aix 19 | 20 | package afero 21 | 22 | import ( 23 | "syscall" 24 | ) 25 | 26 | const BADFD = syscall.EBADFD 27 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/lstater.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Steve Francia . 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package afero 15 | 16 | import ( 17 | "os" 18 | ) 19 | 20 | // Lstater is an optional interface in Afero. It is only implemented by the 21 | // filesystems saying so. 22 | // It will call Lstat if the filesystem iself is, or it delegates to, the os filesystem. 23 | // Else it will call Stat. 24 | // In addtion to the FileInfo, it will return a boolean telling whether Lstat was called or not. 25 | type Lstater interface { 26 | LstatIfPossible(name string) (os.FileInfo, bool, error) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/afero/mem/dir.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2014 Steve Francia . 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package mem 15 | 16 | type Dir interface { 17 | Len() int 18 | Names() []string 19 | Files() []*FileData 20 | Add(*FileData) 21 | Remove(*FileData) 22 | } 23 | 24 | func RemoveFromMemDir(dir *FileData, f *FileData) { 25 | dir.memDir.Remove(f) 26 | } 27 | 28 | func AddToMemDir(dir *FileData, f *FileData) { 29 | dir.memDir.Add(f) 30 | } 31 | 32 | func InitializeDir(d *FileData) { 33 | if d.memDir == nil { 34 | d.dir = true 35 | d.memDir = &DirMap{} 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/terminalstatic/go-xsd-validate/.gitignore: -------------------------------------------------------------------------------- 1 | *.go_ 2 | -------------------------------------------------------------------------------- /vendor/github.com/terminalstatic/go-xsd-validate/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Wolfgang Grimm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/terminalstatic/go-xsd-validate/workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "../../../embedTest" 5 | }, 6 | { 7 | "path": "." 8 | }, 9 | { 10 | "path": "../../../goPost" 11 | } 12 | ], 13 | "settings": {} 14 | } -------------------------------------------------------------------------------- /vendor/github.com/wtolson/go-taglib/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /vendor/github.com/wtolson/go-taglib/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | before_install: 3 | - sudo apt-get update -qq 4 | - sudo apt-get install -qq libtagc0-dev 5 | -------------------------------------------------------------------------------- /vendor/github.com/wtolson/go-taglib/README.md: -------------------------------------------------------------------------------- 1 | go-taglib 2 | ========= 3 | 4 | Go wrapper for [taglib](http://taglib.github.com/) 5 | [![Build Status](https://travis-ci.org/wtolson/go-taglib.png)](https://travis-ci.org/wtolson/go-taglib) 6 | 7 | Dependencies 8 | ------------ 9 | 10 | You must have the static [taglib](http://taglib.github.com/) libraries installed 11 | in order to compile go-taglib. 12 | 13 | ### OSX: 14 | 15 | brew install taglib 16 | 17 | ### Ubuntu: 18 | 19 | sudo apt-get install libtagc0-dev 20 | 21 | Install 22 | ------- 23 | 24 | go get github.com/wtolson/go-taglib 25 | 26 | Documentation 27 | ------------- 28 | 29 | Checkout the documentation at http://godoc.org/github.com/wtolson/go-taglib 30 | -------------------------------------------------------------------------------- /vendor/github.com/wtolson/go-taglib/test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironsmile/euterpe/d69752807dfdd9f1b855a9345d67435af64c34c1/vendor/github.com/wtolson/go-taglib/test.mp3 -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/image/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/image/math/f64/f64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package f64 implements float64 vector and matrix types. 6 | package f64 // import "golang.org/x/image/math/f64" 7 | 8 | // Vec2 is a 2-element vector. 9 | type Vec2 [2]float64 10 | 11 | // Vec3 is a 3-element vector. 12 | type Vec3 [3]float64 13 | 14 | // Vec4 is a 4-element vector. 15 | type Vec4 [4]float64 16 | 17 | // Mat3 is a 3x3 matrix in row major order. 18 | // 19 | // m[3*r + c] is the element in the r'th row and c'th column. 20 | type Mat3 [9]float64 21 | 22 | // Mat4 is a 4x4 matrix in row major order. 23 | // 24 | // m[4*r + c] is the element in the r'th row and c'th column. 25 | type Mat4 [16]float64 26 | 27 | // Aff3 is a 3x3 affine transformation matrix in row major order, where the 28 | // bottom row is implicitly [0 0 1]. 29 | // 30 | // m[3*r + c] is the element in the r'th row and c'th column. 31 | type Aff3 [6]float64 32 | 33 | // Aff4 is a 4x4 affine transformation matrix in row major order, where the 34 | // bottom row is implicitly [0 0 0 1]. 35 | // 36 | // m[4*r + c] is the element in the r'th row and c'th column. 37 | type Aff4 [12]float64 38 | -------------------------------------------------------------------------------- /vendor/golang.org/x/image/tiff/compress.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package tiff 6 | 7 | import ( 8 | "bufio" 9 | "io" 10 | ) 11 | 12 | type byteReader interface { 13 | io.Reader 14 | io.ByteReader 15 | } 16 | 17 | // unpackBits decodes the PackBits-compressed data in src and returns the 18 | // uncompressed data. 19 | // 20 | // The PackBits compression format is described in section 9 (p. 42) 21 | // of the TIFF spec. 22 | func unpackBits(r io.Reader) ([]byte, error) { 23 | buf := make([]byte, 128) 24 | dst := make([]byte, 0, 1024) 25 | br, ok := r.(byteReader) 26 | if !ok { 27 | br = bufio.NewReader(r) 28 | } 29 | 30 | for { 31 | b, err := br.ReadByte() 32 | if err != nil { 33 | if err == io.EOF { 34 | return dst, nil 35 | } 36 | return nil, err 37 | } 38 | code := int(int8(b)) 39 | switch { 40 | case code >= 0: 41 | n, err := io.ReadFull(br, buf[:code+1]) 42 | if err != nil { 43 | return nil, err 44 | } 45 | dst = append(dst, buf[:n]...) 46 | case code == -128: 47 | // No-op. 48 | default: 49 | if b, err = br.ReadByte(); err != nil { 50 | return nil, err 51 | } 52 | for j := 0; j < 1-code; j++ { 53 | buf[j] = b 54 | } 55 | dst = append(dst, buf[:1-code]...) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /vendor/golang.org/x/image/tiff/fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build gofuzz 6 | 7 | package tiff 8 | 9 | import "bytes" 10 | 11 | func Fuzz(data []byte) int { 12 | cfg, err := DecodeConfig(bytes.NewReader(data)) 13 | if err != nil { 14 | return 0 15 | } 16 | if cfg.Width*cfg.Height > 1e6 { 17 | return 0 18 | } 19 | img, err := Decode(bytes.NewReader(data)) 20 | if err != nil { 21 | return 0 22 | } 23 | var w bytes.Buffer 24 | err = Encode(&w, img, nil) 25 | if err != nil { 26 | panic(err) 27 | } 28 | return 1 29 | } 30 | -------------------------------------------------------------------------------- /vendor/golang.org/x/image/webp/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package webp implements a decoder for WEBP images. 6 | // 7 | // WEBP is defined at: 8 | // https://developers.google.com/speed/webp/docs/riff_container 9 | package webp // import "golang.org/x/image/webp" 10 | -------------------------------------------------------------------------------- /vendor/golang.org/x/mod/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/sync/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/unicode/norm/trie.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package norm 6 | 7 | type valueRange struct { 8 | value uint16 // header: value:stride 9 | lo, hi byte // header: lo:n 10 | } 11 | 12 | type sparseBlocks struct { 13 | values []valueRange 14 | offset []uint16 15 | } 16 | 17 | var nfcSparse = sparseBlocks{ 18 | values: nfcSparseValues[:], 19 | offset: nfcSparseOffset[:], 20 | } 21 | 22 | var nfkcSparse = sparseBlocks{ 23 | values: nfkcSparseValues[:], 24 | offset: nfkcSparseOffset[:], 25 | } 26 | 27 | var ( 28 | nfcData = newNfcTrie(0) 29 | nfkcData = newNfkcTrie(0) 30 | ) 31 | 32 | // lookup determines the type of block n and looks up the value for b. 33 | // For n < t.cutoff, the block is a simple lookup table. Otherwise, the block 34 | // is a list of ranges with an accompanying value. Given a matching range r, 35 | // the value for b is by r.value + (b - r.lo) * stride. 36 | func (t *sparseBlocks) lookup(n uint32, b byte) uint16 { 37 | offset := t.offset[n] 38 | header := t.values[offset] 39 | lo := offset + 1 40 | hi := lo + uint16(header.lo) 41 | for lo < hi { 42 | m := lo + (hi-lo)/2 43 | r := t.values[m] 44 | if r.lo <= b && b <= r.hi { 45 | return r.value + uint16(b-r.lo)*header.value 46 | } 47 | if b < r.lo { 48 | hi = m 49 | } else { 50 | lo = m + 1 51 | } 52 | } 53 | return 0 54 | } 55 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/go/ast/astutil/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package astutil 6 | 7 | import "go/ast" 8 | 9 | // Unparen returns e with any enclosing parentheses stripped. 10 | func Unparen(e ast.Expr) ast.Expr { 11 | for { 12 | p, ok := e.(*ast.ParenExpr) 13 | if !ok { 14 | return e 15 | } 16 | e = p.X 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/go/packages/loadmode_string.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package packages 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | ) 11 | 12 | var allModes = []LoadMode{ 13 | NeedName, 14 | NeedFiles, 15 | NeedCompiledGoFiles, 16 | NeedImports, 17 | NeedDeps, 18 | NeedExportFile, 19 | NeedTypes, 20 | NeedSyntax, 21 | NeedTypesInfo, 22 | NeedTypesSizes, 23 | } 24 | 25 | var modeStrings = []string{ 26 | "NeedName", 27 | "NeedFiles", 28 | "NeedCompiledGoFiles", 29 | "NeedImports", 30 | "NeedDeps", 31 | "NeedExportFile", 32 | "NeedTypes", 33 | "NeedSyntax", 34 | "NeedTypesInfo", 35 | "NeedTypesSizes", 36 | } 37 | 38 | func (mod LoadMode) String() string { 39 | m := mod 40 | if m == 0 { 41 | return "LoadMode(0)" 42 | } 43 | var out []string 44 | for i, x := range allModes { 45 | if x > m { 46 | break 47 | } 48 | if (m & x) != 0 { 49 | out = append(out, modeStrings[i]) 50 | m = m ^ x 51 | } 52 | } 53 | if m != 0 { 54 | out = append(out, "Unknown") 55 | } 56 | return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|")) 57 | } 58 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/go/types/typeutil/imports.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package typeutil 6 | 7 | import "go/types" 8 | 9 | // Dependencies returns all dependencies of the specified packages. 10 | // 11 | // Dependent packages appear in topological order: if package P imports 12 | // package Q, Q appears earlier than P in the result. 13 | // The algorithm follows import statements in the order they 14 | // appear in the source code, so the result is a total order. 15 | func Dependencies(pkgs ...*types.Package) []*types.Package { 16 | var result []*types.Package 17 | seen := make(map[*types.Package]bool) 18 | var visit func(pkgs []*types.Package) 19 | visit = func(pkgs []*types.Package) { 20 | for _, p := range pkgs { 21 | if !seen[p] { 22 | seen[p] = true 23 | visit(p.Imports()) 24 | result = append(result, p) 25 | } 26 | } 27 | } 28 | visit(pkgs) 29 | return result 30 | } 31 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/aliases/aliases.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package aliases 6 | 7 | import ( 8 | "go/token" 9 | "go/types" 10 | ) 11 | 12 | // Package aliases defines backward compatible shims 13 | // for the types.Alias type representation added in 1.22. 14 | // This defines placeholders for x/tools until 1.26. 15 | 16 | // NewAlias creates a new TypeName in Package pkg that 17 | // is an alias for the type rhs. 18 | // 19 | // The enabled parameter determines whether the resulting [TypeName]'s 20 | // type is an [types.Alias]. Its value must be the result of a call to 21 | // [Enabled], which computes the effective value of 22 | // GODEBUG=gotypesalias=... by invoking the type checker. The Enabled 23 | // function is expensive and should be called once per task (e.g. 24 | // package import), not once per call to NewAlias. 25 | func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName { 26 | if enabled { 27 | tname := types.NewTypeName(pos, pkg, name, nil) 28 | newAlias(tname, rhs) 29 | return tname 30 | } 31 | return types.NewTypeName(pos, pkg, name, rhs) 32 | } 33 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/aliases/aliases_go121.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !go1.22 6 | // +build !go1.22 7 | 8 | package aliases 9 | 10 | import ( 11 | "go/types" 12 | ) 13 | 14 | // Alias is a placeholder for a go/types.Alias for <=1.21. 15 | // It will never be created by go/types. 16 | type Alias struct{} 17 | 18 | func (*Alias) String() string { panic("unreachable") } 19 | func (*Alias) Underlying() types.Type { panic("unreachable") } 20 | func (*Alias) Obj() *types.TypeName { panic("unreachable") } 21 | func Rhs(alias *Alias) types.Type { panic("unreachable") } 22 | 23 | // Unalias returns the type t for go <=1.21. 24 | func Unalias(t types.Type) types.Type { return t } 25 | 26 | func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") } 27 | 28 | // Enabled reports whether [NewAlias] should create [types.Alias] types. 29 | // 30 | // Before go1.22, this function always returns false. 31 | func Enabled() bool { return false } 32 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/event/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package event provides a set of packages that cover the main 6 | // concepts of telemetry in an implementation agnostic way. 7 | package event 8 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/event/keys/standard.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package keys 6 | 7 | var ( 8 | // Msg is a key used to add message strings to label lists. 9 | Msg = NewString("message", "a readable message") 10 | // Label is a key used to indicate an event adds labels to the context. 11 | Label = NewTag("label", "a label context marker") 12 | // Start is used for things like traces that have a name. 13 | Start = NewString("start", "span start") 14 | // Metric is a key used to indicate an event records metrics. 15 | End = NewTag("end", "a span end marker") 16 | // Metric is a key used to indicate an event records metrics. 17 | Detach = NewTag("detach", "a span detach marker") 18 | // Err is a key used to add error values to label lists. 19 | Err = NewError("error", "an error that occurred") 20 | // Metric is a key used to indicate an event records metrics. 21 | Metric = NewTag("metric", "a metric event marker") 22 | ) 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/event/keys/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package keys 6 | 7 | import ( 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | // Join returns a canonical join of the keys in S: 13 | // a sorted comma-separated string list. 14 | func Join[S ~[]T, T ~string](s S) string { 15 | strs := make([]string, 0, len(s)) 16 | for _, v := range s { 17 | strs = append(strs, string(v)) 18 | } 19 | sort.Strings(strs) 20 | return strings.Join(strs, ",") 21 | } 22 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !go1.11 6 | // +build !go1.11 7 | 8 | package gcimporter 9 | 10 | import "go/types" 11 | 12 | func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { 13 | named := make([]*types.Named, len(embeddeds)) 14 | for i, e := range embeddeds { 15 | var ok bool 16 | named[i], ok = e.(*types.Named) 17 | if !ok { 18 | panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11") 19 | } 20 | } 21 | return types.NewInterface(methods, named) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build go1.11 6 | // +build go1.11 7 | 8 | package gcimporter 9 | 10 | import "go/types" 11 | 12 | func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { 13 | return types.NewInterfaceType(methods, embeddeds) 14 | } 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/gcimporter/support_go118.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gcimporter 6 | 7 | import "go/types" 8 | 9 | const iexportVersion = iexportVersionGenerics 10 | 11 | // additionalPredeclared returns additional predeclared types in go.1.18. 12 | func additionalPredeclared() []types.Type { 13 | return []types.Type{ 14 | // comparable 15 | types.Universe.Lookup("comparable").Type(), 16 | 17 | // any 18 | types.Universe.Lookup("any").Type(), 19 | } 20 | } 21 | 22 | // See cmd/compile/internal/types.SplitVargenSuffix. 23 | func splitVargenSuffix(name string) (base, suffix string) { 24 | i := len(name) 25 | for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' { 26 | i-- 27 | } 28 | const dot = "·" 29 | if i >= len(dot) && name[i-len(dot):i] == dot { 30 | i -= len(dot) 31 | return name[:i], name[i:] 32 | } 33 | return name, "" 34 | } 35 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/gcimporter/unified_no.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !goexperiment.unified 6 | // +build !goexperiment.unified 7 | 8 | package gcimporter 9 | 10 | const unifiedIR = false 11 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build goexperiment.unified 6 | // +build goexperiment.unified 7 | 8 | package gcimporter 9 | 10 | const unifiedIR = true 11 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/packagesinternal/packages.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package packagesinternal exposes internal-only fields from go/packages. 6 | package packagesinternal 7 | 8 | var GetForTest = func(p interface{}) string { return "" } 9 | var GetDepsErrors = func(p interface{}) []*PackageError { return nil } 10 | 11 | type PackageError struct { 12 | ImportStack []string // shortest path from package named on command line to this one 13 | Pos string // position of error (if present, file:line:col) 14 | Err string // the error itself 15 | } 16 | 17 | var TypecheckCgo int 18 | var DepsErrors int // must be set as a LoadMode to call GetDepsErrors 19 | var ForTest int // must be set as a LoadMode to call GetForTest 20 | 21 | var SetModFlag = func(config interface{}, value string) {} 22 | var SetModFile = func(config interface{}, value string) {} 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/pkgbits/flags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package pkgbits 6 | 7 | const ( 8 | flagSyncMarkers = 1 << iota // file format contains sync markers 9 | ) 10 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !go1.7 6 | // +build !go1.7 7 | 8 | // TODO(mdempsky): Remove after #44505 is resolved 9 | 10 | package pkgbits 11 | 12 | import "runtime" 13 | 14 | func walkFrames(pcs []uintptr, visit frameVisitor) { 15 | for _, pc := range pcs { 16 | fn := runtime.FuncForPC(pc) 17 | file, line := fn.FileLine(pc) 18 | 19 | visit(file, line, fn.Name(), pc-fn.Entry()) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build go1.7 6 | // +build go1.7 7 | 8 | package pkgbits 9 | 10 | import "runtime" 11 | 12 | // walkFrames calls visit for each call frame represented by pcs. 13 | // 14 | // pcs should be a slice of PCs, as returned by runtime.Callers. 15 | func walkFrames(pcs []uintptr, visit frameVisitor) { 16 | if len(pcs) == 0 { 17 | return 18 | } 19 | 20 | frames := runtime.CallersFrames(pcs) 21 | for { 22 | frame, more := frames.Next() 23 | visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry) 24 | if !more { 25 | return 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/pkgbits/reloc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package pkgbits 6 | 7 | // A RelocKind indicates a particular section within a unified IR export. 8 | type RelocKind int32 9 | 10 | // An Index represents a bitstream element index within a particular 11 | // section. 12 | type Index int32 13 | 14 | // A relocEnt (relocation entry) is an entry in an element's local 15 | // reference table. 16 | // 17 | // TODO(mdempsky): Rename this too. 18 | type RelocEnt struct { 19 | Kind RelocKind 20 | Idx Index 21 | } 22 | 23 | // Reserved indices within the meta relocation section. 24 | const ( 25 | PublicRootIdx Index = 0 26 | PrivateRootIdx Index = 1 27 | ) 28 | 29 | const ( 30 | RelocString RelocKind = iota 31 | RelocMeta 32 | RelocPosBase 33 | RelocPkg 34 | RelocName 35 | RelocType 36 | RelocObj 37 | RelocObjExt 38 | RelocObjDict 39 | RelocBody 40 | 41 | numRelocs = iota 42 | ) 43 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/pkgbits/support.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package pkgbits 6 | 7 | import "fmt" 8 | 9 | func assert(b bool) { 10 | if !b { 11 | panic("assertion failed") 12 | } 13 | } 14 | 15 | func errorf(format string, args ...interface{}) { 16 | panic(fmt.Errorf(format, args...)) 17 | } 18 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/typesinternal/recv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package typesinternal 6 | 7 | import ( 8 | "go/types" 9 | 10 | "golang.org/x/tools/internal/aliases" 11 | ) 12 | 13 | // ReceiverNamed returns the named type (if any) associated with the 14 | // type of recv, which may be of the form N or *N, or aliases thereof. 15 | // It also reports whether a Pointer was present. 16 | func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) { 17 | t := recv.Type() 18 | if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok { 19 | isPtr = true 20 | t = ptr.Elem() 21 | } 22 | named, _ = aliases.Unalias(t).(*types.Named) 23 | return 24 | } 25 | 26 | // Unpointer returns T given *T or an alias thereof. 27 | // For all other types it is the identity function. 28 | // It does not look at underlying types. 29 | // The result may be an alias. 30 | // 31 | // Use this function to strip off the optional pointer on a receiver 32 | // in a field or method selection, without losing the named type 33 | // (which is needed to compute the method set). 34 | // 35 | // See also [typeparams.MustDeref], which removes one level of 36 | // indirection from the type, regardless of named types (analogous to 37 | // a LOAD instruction). 38 | func Unpointer(t types.Type) types.Type { 39 | if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok { 40 | return ptr.Elem() 41 | } 42 | return t 43 | } 44 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/features.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package versions 6 | 7 | // This file contains predicates for working with file versions to 8 | // decide when a tool should consider a language feature enabled. 9 | 10 | // GoVersions that features in x/tools can be gated to. 11 | const ( 12 | Go1_18 = "go1.18" 13 | Go1_19 = "go1.19" 14 | Go1_20 = "go1.20" 15 | Go1_21 = "go1.21" 16 | Go1_22 = "go1.22" 17 | ) 18 | 19 | // Future is an invalid unknown Go version sometime in the future. 20 | // Do not use directly with Compare. 21 | const Future = "" 22 | 23 | // AtLeast reports whether the file version v comes after a Go release. 24 | // 25 | // Use this predicate to enable a behavior once a certain Go release 26 | // has happened (and stays enabled in the future). 27 | func AtLeast(v, release string) bool { 28 | if v == Future { 29 | return true // an unknown future version is always after y. 30 | } 31 | return Compare(Lang(v), Lang(release)) >= 0 32 | } 33 | 34 | // Before reports whether the file version v is strictly before a Go release. 35 | // 36 | // Use this predicate to disable a behavior once a certain Go release 37 | // has happened (and stays enabled in the future). 38 | func Before(v, release string) bool { 39 | if v == Future { 40 | return false // an unknown future version happens after y. 41 | } 42 | return Compare(Lang(v), Lang(release)) < 0 43 | } 44 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/toolchain.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package versions 6 | 7 | // toolchain is maximum version (<1.22) that the go toolchain used 8 | // to build the current tool is known to support. 9 | // 10 | // When a tool is built with >=1.22, the value of toolchain is unused. 11 | // 12 | // x/tools does not support building with go <1.18. So we take this 13 | // as the minimum possible maximum. 14 | var toolchain string = Go1_18 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/toolchain_go119.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build go1.19 6 | // +build go1.19 7 | 8 | package versions 9 | 10 | func init() { 11 | if Compare(toolchain, Go1_19) < 0 { 12 | toolchain = Go1_19 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/toolchain_go120.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build go1.20 6 | // +build go1.20 7 | 8 | package versions 9 | 10 | func init() { 11 | if Compare(toolchain, Go1_20) < 0 { 12 | toolchain = Go1_20 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/toolchain_go121.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build go1.21 6 | // +build go1.21 7 | 8 | package versions 9 | 10 | func init() { 11 | if Compare(toolchain, Go1_21) < 0 { 12 | toolchain = Go1_21 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/types.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package versions 6 | 7 | import ( 8 | "go/types" 9 | ) 10 | 11 | // GoVersion returns the Go version of the type package. 12 | // It returns zero if no version can be determined. 13 | func GoVersion(pkg *types.Package) string { 14 | // TODO(taking): x/tools can call GoVersion() [from 1.21] after 1.25. 15 | if pkg, ok := any(pkg).(interface{ GoVersion() string }); ok { 16 | return pkg.GoVersion() 17 | } 18 | return "" 19 | } 20 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/internal/versions/types_go121.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !go1.22 6 | // +build !go1.22 7 | 8 | package versions 9 | 10 | import ( 11 | "go/ast" 12 | "go/types" 13 | ) 14 | 15 | // FileVersion returns a language version (<=1.21) derived from runtime.Version() 16 | // or an unknown future version. 17 | func FileVersion(info *types.Info, file *ast.File) string { 18 | // In x/tools built with Go <= 1.21, we do not have Info.FileVersions 19 | // available. We use a go version derived from the toolchain used to 20 | // compile the tool by default. 21 | // This will be <= go1.21. We take this as the maximum version that 22 | // this tool can support. 23 | // 24 | // There are no features currently in x/tools that need to tell fine grained 25 | // differences for versions <1.22. 26 | return toolchain 27 | } 28 | 29 | // InitFileVersions is a noop when compiled with this Go version. 30 | func InitFileVersions(*types.Info) {} 31 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/README: -------------------------------------------------------------------------------- 1 | This repository holds the transition packages for the new Go 1.13 error values. 2 | See golang.org/design/29934-error-values. 3 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/codereview.cfg: -------------------------------------------------------------------------------- 1 | issuerepo: golang/go 2 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package xerrors implements functions to manipulate errors. 6 | // 7 | // This package is based on the Go 2 proposal for error values: 8 | // https://golang.org/design/29934-error-values 9 | // 10 | // These functions were incorporated into the standard library's errors package 11 | // in Go 1.13: 12 | // - Is 13 | // - As 14 | // - Unwrap 15 | // 16 | // Also, Errorf's %w verb was incorporated into fmt.Errorf. 17 | // 18 | // Use this package to get equivalent behavior in all supported Go versions. 19 | // 20 | // No other features of this package were included in Go 1.13, and at present 21 | // there are no plans to include any of them. 22 | package xerrors // import "golang.org/x/xerrors" 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import "fmt" 8 | 9 | // errorString is a trivial implementation of error. 10 | type errorString struct { 11 | s string 12 | frame Frame 13 | } 14 | 15 | // New returns an error that formats as the given text. 16 | // 17 | // The returned error contains a Frame set to the caller's location and 18 | // implements Formatter to show this information when printed with details. 19 | func New(text string) error { 20 | return &errorString{text, Caller(1)} 21 | } 22 | 23 | func (e *errorString) Error() string { 24 | return e.s 25 | } 26 | 27 | func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) } 28 | 29 | func (e *errorString) FormatError(p Printer) (next error) { 30 | p.Print(e.s) 31 | e.frame.Format(p) 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/format.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | // A Formatter formats error messages. 8 | type Formatter interface { 9 | error 10 | 11 | // FormatError prints the receiver's first error and returns the next error in 12 | // the error chain, if any. 13 | FormatError(p Printer) (next error) 14 | } 15 | 16 | // A Printer formats error messages. 17 | // 18 | // The most common implementation of Printer is the one provided by package fmt 19 | // during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message 20 | // typically provide their own implementations. 21 | type Printer interface { 22 | // Print appends args to the message output. 23 | Print(args ...interface{}) 24 | 25 | // Printf writes a formatted string. 26 | Printf(format string, args ...interface{}) 27 | 28 | // Detail reports whether error detail is requested. 29 | // After the first call to Detail, all text written to the Printer 30 | // is formatted as additional detail, or ignored when 31 | // detail has not been requested. 32 | // If Detail returns false, the caller can avoid printing the detail at all. 33 | Detail() bool 34 | } 35 | -------------------------------------------------------------------------------- /vendor/golang.org/x/xerrors/internal/internal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package internal 6 | 7 | // EnableTrace indicates whether stack information should be recorded in errors. 8 | var EnableTrace = true 9 | -------------------------------------------------------------------------------- /vendor/gopkg.in/gorp.v1/.gitignore: -------------------------------------------------------------------------------- 1 | _test 2 | _testmain.go 3 | _obj 4 | *~ 5 | *.6 6 | 6.out 7 | gorptest.bin 8 | tmp 9 | -------------------------------------------------------------------------------- /vendor/gopkg.in/gorp.v1/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1 4 | - tip 5 | 6 | services: 7 | - mysql 8 | - postgres 9 | - sqlite3 10 | 11 | before_script: 12 | - mysql -e "CREATE DATABASE gorptest;" 13 | - mysql -u root -e "GRANT ALL ON gorptest.* TO gorptest@localhost IDENTIFIED BY 'gorptest'" 14 | - psql -c "CREATE DATABASE gorptest;" -U postgres 15 | - psql -c "CREATE USER "gorptest" WITH SUPERUSER PASSWORD 'gorptest';" -U postgres 16 | - go get github.com/lib/pq 17 | - go get github.com/mattn/go-sqlite3 18 | - go get github.com/ziutek/mymysql/godrv 19 | - go get github.com/go-sql-driver/mysql 20 | 21 | script: ./test_all.sh 22 | -------------------------------------------------------------------------------- /vendor/gopkg.in/gorp.v1/LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012 James Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/gopkg.in/gorp.v1/Makefile: -------------------------------------------------------------------------------- 1 | include $(GOROOT)/src/Make.inc 2 | 3 | TARG = github.com/coopernurse/gorp 4 | GOFILES = gorp.go dialect.go 5 | 6 | include $(GOROOT)/src/Make.pkg -------------------------------------------------------------------------------- /vendor/gopkg.in/gorp.v1/errors.go: -------------------------------------------------------------------------------- 1 | package gorp 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // A non-fatal error, when a select query returns columns that do not exist 8 | // as fields in the struct it is being mapped to 9 | type NoFieldInTypeError struct { 10 | TypeName string 11 | MissingColNames []string 12 | } 13 | 14 | func (err *NoFieldInTypeError) Error() string { 15 | return fmt.Sprintf("gorp: No fields %+v in type %s", err.MissingColNames, err.TypeName) 16 | } 17 | 18 | // returns true if the error is non-fatal (ie, we shouldn't immediately return) 19 | func NonFatalError(err error) bool { 20 | switch err.(type) { 21 | case *NoFieldInTypeError: 22 | return true 23 | default: 24 | return false 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/gopkg.in/gorp.v1/test_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # on macs, you may need to: 4 | # export GOBUILDFLAG=-ldflags -linkmode=external 5 | 6 | set -e 7 | 8 | export GORP_TEST_DSN=gorptest/gorptest/gorptest 9 | export GORP_TEST_DIALECT=mysql 10 | go test $GOBUILDFLAG . 11 | 12 | export GORP_TEST_DSN=gorptest:gorptest@/gorptest 13 | export GORP_TEST_DIALECT=gomysql 14 | go test $GOBUILDFLAG . 15 | 16 | export GORP_TEST_DSN="user=gorptest password=gorptest dbname=gorptest sslmode=disable" 17 | export GORP_TEST_DIALECT=postgres 18 | go test $GOBUILDFLAG . 19 | 20 | export GORP_TEST_DSN=/tmp/gorptest.bin 21 | export GORP_TEST_DIALECT=sqlite 22 | go test $GOBUILDFLAG . 23 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "tip" 5 | - "1.10" 6 | - "1.9" 7 | - "1.8" 8 | - "1.7" 9 | - "1.6" 10 | - "1.5" 11 | - "1.4" 12 | - "1.3" 13 | - "1.2" 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Wieland Hoffmann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/README.md: -------------------------------------------------------------------------------- 1 | # gocaa 2 | 3 | [![Build Status](https://travis-ci.org/mineo/gocaa.svg?branch=master)](https://travis-ci.org/mineo/gocaa) 4 | [![GoDoc](https://godoc.org/gopkg.in/mineo/gocaa.v1?status.svg)](https://godoc.org/gopkg.in/mineo/gocaa.v1) 5 | 6 | This package contains a library to access the 7 | [Cover Art Archive](https://coverartarchive.org) from Go. 8 | 9 | ## Installation 10 | To get the latest stable version, user 11 | 12 | go get gopkg.in/mineo/gocaa.v1 13 | 14 | and import it with 15 | 16 | import "gopkg.in/mineo/gocaa.v1" 17 | 18 | To get the latest version, use 19 | 20 | go get github.com/mineo/gocaa 21 | 22 | and import it with 23 | 24 | import "github.com/mineo/gocaa" 25 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/errors.go: -------------------------------------------------------------------------------- 1 | package caa 2 | 3 | import ( 4 | "fmt" 5 | "net/url" 6 | ) 7 | 8 | // HTTPError is an error that occured while accessing URL. 9 | // Instead of a status code of 200, StatusCode was returned by the server. 10 | type HTTPError struct { 11 | StatusCode int 12 | URL *url.URL 13 | } 14 | 15 | func (e HTTPError) Error() string { 16 | return fmt.Sprintf("%d on %s", e.StatusCode, e.URL.String()) 17 | } 18 | 19 | // InvalidImageSizeError indicates that Size is not valid for EntityType 20 | type InvalidImageSizeError struct { 21 | EntityType string 22 | Size int 23 | } 24 | 25 | func (e InvalidImageSizeError) Error() string { 26 | return fmt.Sprintf("%s doesn't support image size %d", e.EntityType, e.Size) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/imagesizes.go: -------------------------------------------------------------------------------- 1 | package caa 2 | 3 | // These constants can be used to indicate the required image size to the various image retrieval methods 4 | const ( 5 | // 250px 6 | ImageSizeSmall = iota 7 | // 500px 8 | ImageSizeLarge 9 | ImageSizeOriginal 10 | // 250px 11 | ImageSize250 = ImageSizeSmall 12 | // 500px 13 | ImageSize500 = ImageSizeLarge 14 | // 1200px 15 | ImageSize1200 16 | ) 17 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/reexports.go: -------------------------------------------------------------------------------- 1 | package caa 2 | 3 | import ( 4 | u "github.com/pborman/uuid" 5 | ) 6 | 7 | // StringToUUID is a reexported helper function of the UUID module to parse a 8 | // string into a UUID. 9 | func StringToUUID(str string) (uuid u.UUID) { 10 | return u.Parse(str) 11 | } 12 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mineo/gocaa.v1/types.go: -------------------------------------------------------------------------------- 1 | package caa 2 | 3 | // CoverArtInfo is the unmarshaled representation of a JSON file in the Cover Art Archive. 4 | // See https://musicbrainz.org/doc/Cover_Art_Archive/API#Cover_Art_Archive_Metadata for an example. 5 | type CoverArtInfo struct { 6 | Images []CoverArtImageInfo 7 | Release string 8 | } 9 | 10 | // CoverArtImageInfo is the unmarshaled representation of a single images metadata in a CAA JSON file. 11 | // See https://musicbrainz.org/doc/Cover_Art_Archive/API#Cover_Art_Archive_Metadata for an example. 12 | type CoverArtImageInfo struct { 13 | Approved bool 14 | Back bool 15 | Comment string 16 | Edit int 17 | Front bool 18 | ID string 19 | Image string 20 | Thumbnails ThumbnailMap 21 | Types []string 22 | } 23 | 24 | // CoverArtImage is a wrapper around an image from the CAA, containing its binary data and mimetype information. 25 | type CoverArtImage struct { 26 | Data []byte 27 | Mimetype string 28 | } 29 | 30 | // ThumbnailMap maps thumbnail names to their URLs. The only valid keys are 31 | // "large" and "small", "250", "500" and "1200". 32 | type ThumbnailMap map[string]string 33 | -------------------------------------------------------------------------------- /watch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script will watch for changes in the .css or .js files of the project 4 | # and rebuild the "squashed" versions which are to be released. 5 | 6 | find . -type f -name '*.css' -or -name '*.js' | grep -v '.min.' | entr ./http_root/squash 7 | --------------------------------------------------------------------------------