Auth: Apply user rights and permissions in the search API #98 #782

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2022-09-30 00:42:19 +02:00
parent 47929566db
commit 323d495840
172 changed files with 2149 additions and 12236 deletions

View File

@@ -507,6 +507,9 @@ fmt-go:
goimports -w pkg internal cmd goimports -w pkg internal cmd
tidy: tidy:
go mod tidy -go=1.16 && go mod tidy -go=1.17 go mod tidy -go=1.16 && go mod tidy -go=1.17
users:
./photoprism users add -p photoprism -r admin -s -a test:true -n "Alice Austen" superadmin
./photoprism users ls
# Declare all targets as "PHONY", see https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html. # Declare all targets as "PHONY", see https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html.
MAKEFLAGS += --always-make MAKEFLAGS += --always-make

View File

@@ -233,6 +233,12 @@ export default [
component: Places, component: Places,
meta: { title: $gettext("Places"), auth: true }, meta: { title: $gettext("Places"), auth: true },
}, },
{
name: "album_place",
path: "/places/:album/:q",
component: Places,
meta: { title: $gettext("Places"), auth: true },
},
{ {
name: "states", name: "states",
path: "/states", path: "/states",

View File

@@ -355,18 +355,45 @@ export default class Config {
return result; return result;
} }
// allow checks whether the current user is granted permission for the specified resource.
allow(resource, perm) { allow(resource, perm) {
if (this.values["acl"] && this.values["acl"][resource]) { if (this.values["acl"] && this.values["acl"][resource]) {
return !!this.values["acl"][resource][perm] || !!this.values["acl"][resource]["full_access"]; if (this.values["acl"][resource]["full_access"]) {
return true;
} else if (this.values["acl"][resource][perm]) {
return true;
}
} }
return false; return false;
} }
// allowAny checks whether the current user is granted any of the permissions for the specified resource.
allowAny(resource, perms) {
if (this.values["acl"] && this.values["acl"][resource]) {
if (this.values["acl"][resource]["full_access"]) {
return true;
}
for (const perm of perms) {
if (this.values["acl"][resource][perm]) {
return true;
}
}
}
return false;
}
// deny checks whether the current user must be denied access to the specified resource.
deny(resource, perm) { deny(resource, perm) {
return !this.allow(resource, perm); return !this.allow(resource, perm);
} }
// denyAll checks whether the current user is granted none of the permissions for the specified resource.
denyAll(resource, perm) {
return !this.allowAny(resource, perm);
}
settings() { settings() {
return this.values.settings; return this.values.settings;
} }

View File

@@ -77,7 +77,9 @@ export default class Session {
}); });
// Say hello. // Say hello.
this.refresh().then(() => {
this.sendClientInfo(); this.sendClientInfo();
});
} }
useSessionStorage() { useSessionStorage() {
@@ -253,6 +255,27 @@ export default class Session {
}); });
} }
refresh() {
if (this.hasId()) {
return Api.get("session/" + this.getId())
.then((resp) => {
if (resp.data && resp.data.config) {
this.setConfig(resp.data.config);
this.setUser(resp.data.user);
this.setData(resp.data.data);
}
return Promise.resolve();
})
.catch(() => {
this.deleteId();
window.location.reload();
return Promise.reject();
});
} else {
return Promise.resolve();
}
}
redeemToken(token) { redeemToken(token) {
return Api.post("session", { token }).then((resp) => { return Api.post("session", { token }).then((resp) => {
this.setConfig(resp.data.config); this.setConfig(resp.data.config);

View File

@@ -153,6 +153,10 @@ export default class Util {
return s.replace(/\w\S*/g, (w) => w.replace(/^\w/, (c) => c.toUpperCase())); return s.replace(/\w\S*/g, (w) => w.replace(/^\w/, (c) => c.toUpperCase()));
} }
static generateToken() {
return (Math.random() + 1).toString(36).substring(6);
}
static fileType(value) { static fileType(value) {
if (!value || typeof value !== "string") { if (!value || typeof value !== "string") {
return ""; return "";

View File

@@ -111,7 +111,7 @@ export default {
}].concat(this.$config.get('countries')); }].concat(this.$config.get('countries'));
const features = this.$config.settings().features; const features = this.$config.settings().features;
return { return {
canUpload: this.$config.allow("albums", "upload") && features.upload, canUpload: this.$config.allow("files", "upload") && features.upload,
canDownload: this.$config.allow("albums", "download") && features.download, canDownload: this.$config.allow("albums", "download") && features.download,
canShare: this.$config.allow("albums", "share") && features.share, canShare: this.$config.allow("albums", "share") && features.share,
canManage: this.$config.allow("albums", "manage"), canManage: this.$config.allow("albums", "manage"),

View File

@@ -36,11 +36,10 @@
<v-icon>cloud_download</v-icon> <v-icon>cloud_download</v-icon>
</v-btn --> </v-btn -->
<v-btn <v-btn
v-if="$config.feature('albums')"
fab dark small fab dark small
:title="$gettext('Add to album')" :title="$gettext('Add to album')"
color="album" color="album"
:disabled="selection.length === 0" :disabled="!canAddAlbums || selection.length === 0"
class="action-album" class="action-album"
@click.stop="dialog.album = true" @click.stop="dialog.album = true"
> >
@@ -50,7 +49,7 @@
fab dark small fab dark small
color="remove" color="remove"
:title="$gettext('Delete')" :title="$gettext('Delete')"
:disabled="selection.length === 0" :disabled="!canManage || selection.length === 0"
class="action-delete" class="action-delete"
@click.stop="dialog.delete = true" @click.stop="dialog.delete = true"
> >
@@ -85,11 +84,20 @@ export default {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
refresh: Function, refresh: {
clearSelection: Function, type: Function,
default: () => {},
},
clearSelection: {
type: Function,
default: () => {},
},
}, },
data() { data() {
return { return {
canManage: this.$config.allow("labels", "manage"),
canDownload: this.$config.allow("labels", "download"),
canAddAlbums: this.$config.allow("albums", "create") && this.$config.feature("albums"),
expanded: false, expanded: false,
dialog: { dialog: {
delete: false, delete: false,
@@ -105,6 +113,10 @@ export default {
this.expanded = false; this.expanded = false;
}, },
addToAlbum(ppid) { addToAlbum(ppid) {
if (!this.canAddAlbums) {
return;
}
this.dialog.album = false; this.dialog.album = false;
Api.post(`albums/${ppid}/photos`, {"labels": this.selection}).then(() => this.onAdded()); Api.post(`albums/${ppid}/photos`, {"labels": this.selection}).then(() => this.onAdded());
@@ -113,6 +125,10 @@ export default {
this.clearClipboard(); this.clearClipboard();
}, },
batchDelete() { batchDelete() {
if (!this.canManage) {
return;
}
this.dialog.delete = false; this.dialog.delete = false;
Api.post("batch/labels/delete", {"labels": this.selection}).then(this.onDeleted.bind(this)); Api.post("batch/labels/delete", {"labels": this.selection}).then(this.onDeleted.bind(this));
@@ -122,6 +138,10 @@ export default {
this.clearClipboard(); this.clearClipboard();
}, },
download() { download() {
if (!this.canDownload) {
return;
}
if (this.selection.length !== 1) { if (this.selection.length !== 1) {
Notify.error(this.$gettext("You can only download one label")); Notify.error(this.$gettext("You can only download one label"));
return; return;

View File

@@ -70,7 +70,7 @@
</v-toolbar> </v-toolbar>
<v-list class="pt-3 p-flex-menu"> <v-list class="pt-3 p-flex-menu">
<v-list-tile v-if="isMini" class="nav-expand" @click.stop="toggleIsMini()"> <v-list-tile v-if="isMini && !isRestricted" class="nav-expand" @click.stop="toggleIsMini()">
<v-list-tile-action :title="$gettext('Expand')"> <v-list-tile-action :title="$gettext('Expand')">
<v-icon v-if="!rtl">chevron_right</v-icon> <v-icon v-if="!rtl">chevron_right</v-icon>
<v-icon v-else>chevron_left</v-icon> <v-icon v-else>chevron_left</v-icon>
@@ -165,7 +165,7 @@
</v-list-tile> </v-list-tile>
</v-list-group> </v-list-group>
<v-list-tile v-if="isMini && $config.feature('albums')" to="/albums" class="nav-albums" @click.stop=""> <v-list-tile v-if="isMini" v-show="$config.feature('albums')" to="/albums" class="nav-albums" @click.stop="">
<v-list-tile-action :title="$gettext('Albums')"> <v-list-tile-action :title="$gettext('Albums')">
<v-icon>bookmark</v-icon> <v-icon>bookmark</v-icon>
</v-list-tile-action> </v-list-tile-action>
@@ -177,8 +177,7 @@
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<template v-if="!isMini && $config.feature('albums')"> <v-list-group v-if="!isMini" v-show="$config.feature('albums')" prepend-icon="bookmark" no-action>
<v-list-group v-if="canSearch" prepend-icon="bookmark" no-action>
<template #activator> <template #activator>
<v-list-tile :to="{ name: 'albums' }" class="nav-albums" @click.stop=""> <v-list-tile :to="{ name: 'albums' }" class="nav-albums" @click.stop="">
<v-list-tile-content> <v-list-tile-content>
@@ -199,20 +198,6 @@
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
</v-list-group> </v-list-group>
<v-list-tile v-else :to="{ name: 'albums' }" class="nav-albums" @click.stop="">
<v-list-tile-action :title="$gettext('Albums')">
<v-icon>bookmark</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title class="p-flex-menuitem">
<translate key="Albums">Albums</translate>
<span v-if="config.count.albums > 0"
:class="`nav-count ${rtl ? '--rtl' : ''}`">{{ config.count.albums | abbreviateCount }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<v-list-tile v-if="isMini && $config.feature('videos')" to="/videos" class="nav-video" @click.stop=""> <v-list-tile v-if="isMini && $config.feature('videos')" to="/videos" class="nav-video" @click.stop="">
<v-list-tile-action :title="$gettext('Videos')"> <v-list-tile-action :title="$gettext('Videos')">
@@ -307,7 +292,7 @@
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<v-list-tile v-if="isMini" v-show="$config.feature('places')" :to="{ name: 'places' }" class="nav-places" <v-list-tile v-if="isMini" v-show="canSearchPlaces && $config.feature('places')" :to="{ name: 'places' }" class="nav-places"
@click.stop=""> @click.stop="">
<v-list-tile-action :title="$gettext('Places')"> <v-list-tile-action :title="$gettext('Places')">
<v-icon>place</v-icon> <v-icon>place</v-icon>
@@ -320,7 +305,7 @@
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<v-list-group v-if="!isMini" v-show="$config.feature('places')" prepend-icon="place" no-action> <v-list-group v-if="!isMini" v-show="canSearchPlaces && $config.feature('places')" prepend-icon="place" no-action>
<template #activator> <template #activator>
<v-list-tile to="/places" class="nav-places" @click.stop=""> <v-list-tile to="/places" class="nav-places" @click.stop="">
<v-list-tile-content> <v-list-tile-content>
@@ -578,7 +563,7 @@
</a> </a>
</div> </div>
<div class="menu-actions"> <div class="menu-actions">
<div v-if="auth && !routeName('browse')" class="menu-action nav-search"> <div v-if="auth && !routeName('browse')&& $config.feature('search')" class="menu-action nav-search">
<router-link to="/browse"> <router-link to="/browse">
<v-icon>search</v-icon> <v-icon>search</v-icon>
<translate>Search</translate> <translate>Search</translate>
@@ -596,7 +581,7 @@
<translate>People</translate> <translate>People</translate>
</router-link> </router-link>
</div> </div>
<div v-if="auth && !routeName('places') && $config.feature('places')" class="menu-action nav-places"> <div v-if="auth && canSearchPlaces && !routeName('places') && $config.feature('places')" class="menu-action nav-places">
<router-link to="/places"> <router-link to="/places">
<v-icon>place</v-icon> <v-icon>place</v-icon>
<translate>Places</translate> <translate>Places</translate>
@@ -683,8 +668,11 @@ export default {
appNameSuffix = appNameParts.slice(1, 9).join(" "); appNameSuffix = appNameParts.slice(1, 9).join(" ");
} }
const isRestricted= this.$config.deny("photos", "access_library");
return { return {
canSearch: this.$config.allow("photos", "search"), canSearchPlaces: this.$config.allow("places", "search"),
canAccessAll: !isRestricted,
canManagePeople: this.$config.allow("people", "manage"), canManagePeople: this.$config.allow("people", "manage"),
appNameSuffix: appNameSuffix, appNameSuffix: appNameSuffix,
appName: this.$config.getName(), appName: this.$config.getName(),
@@ -692,7 +680,8 @@ export default {
appIcon: this.$config.getIcon(), appIcon: this.$config.getIcon(),
indexing: false, indexing: false,
drawer: null, drawer: null,
isMini: localStorage.getItem('last_navigation_mode') !== 'false', isRestricted: isRestricted,
isMini: localStorage.getItem('last_navigation_mode') !== 'false' || isRestricted,
isPublic: this.$config.get("public"), isPublic: this.$config.get("public"),
isDemo: this.$config.get("demo"), isDemo: this.$config.get("demo"),
isAdmin: this.$session.isAdmin(), isAdmin: this.$session.isAdmin(),
@@ -790,7 +779,7 @@ export default {
showNavigation() { showNavigation() {
if (this.auth) { if (this.auth) {
this.drawer = true; this.drawer = true;
this.isMini = false; this.isMini = this.isRestricted;
} }
}, },
createAlbum() { createAlbum() {

View File

@@ -24,19 +24,18 @@
</template> </template>
<v-btn <v-btn
v-if="features.download"
fab dark small fab dark small
:title="$gettext('Download')" :title="$gettext('Download')"
color="download" color="download"
class="action-download" class="action-download"
:disabled="selection.length !== 1" :disabled="!canDownload || selection.length !== 1"
@click.stop="download()" @click.stop="download()"
> >
<v-icon>get_app</v-icon> <v-icon>get_app</v-icon>
</v-btn> </v-btn>
<v-btn <v-btn
v-if="features.albums" v-if="canAddAlbums"
fab dark small fab dark small
:title="$gettext('Add to album')" :title="$gettext('Add to album')"
color="album" color="album"
@@ -73,11 +72,20 @@ export default {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
refresh: Function, refresh: {
clearSelection: Function, type: Function,
default: () => {},
},
clearSelection: {
type: Function,
default: () => {},
},
}, },
data() { data() {
return { return {
canManage: this.$config.allow("people", "manage"),
canDownload: this.$config.allow("people", "download") && this.$config.feature("download"),
canAddAlbums: this.$config.allow("albums", "create") && this.$config.feature("albums"),
features: this.$config.settings().features, features: this.$config.settings().features,
expanded: false, expanded: false,
dialog: { dialog: {

View File

@@ -347,6 +347,10 @@ body.chrome #photoprism .search-results .result {
visibility: hidden; visibility: hidden;
} }
#photoprism .disable-manage .search-results .result .input-favorite.v-btn:before {
visibility: hidden;
}
#photoprism .cards-view .input-reject, #photoprism .cards-view .input-reject,
#photoprism .mosaic-view .input-reject { #photoprism .mosaic-view .input-reject {
opacity: 0.75; opacity: 0.75;

View File

@@ -90,6 +90,7 @@
import Api from "common/api"; import Api from "common/api";
import Notify from "common/notify"; import Notify from "common/notify";
import Album from "model/album"; import Album from "model/album";
import Util from "common/util";
export default { export default {
name: 'PTabUpload', name: 'PTabUpload',
@@ -109,7 +110,7 @@ export default {
current: 0, current: 0,
total: 0, total: 0,
completed: 0, completed: 0,
started: 0, token: "",
review: this.$config.feature("review"), review: this.$config.feature("review"),
safe: !this.$config.get("uploadNSFW"), safe: !this.$config.get("uploadNSFW"),
rtl: this.$rtl, rtl: this.$rtl,
@@ -174,7 +175,7 @@ export default {
this.current = 0; this.current = 0;
this.total = 0; this.total = 0;
this.completed = 0; this.completed = 0;
this.started = 0; this.token = "";
}, },
upload() { upload() {
if (this.busy) { if (this.busy) {
@@ -188,7 +189,7 @@ export default {
return; return;
} }
this.started = Date.now(); this.token = Util.generateToken();
this.selected = this.$refs.upload.files; this.selected = this.$refs.upload.files;
this.total = this.selected.length; this.total = this.selected.length;
this.busy = true; this.busy = true;
@@ -221,7 +222,7 @@ export default {
formData.append('files', file); formData.append('files', file);
await Api.post('upload/' + ctx.started, await Api.post('upload/' + ctx.token,
formData, formData,
{ {
headers: { headers: {
@@ -240,7 +241,7 @@ export default {
this.indexing = true; this.indexing = true;
const ctx = this; const ctx = this;
Api.post('import/upload/' + this.started, { Api.post('import/upload/' + this.token, {
move: true, move: true,
albums: addToAlbums, albums: addToAlbums,
}).then(() => { }).then(() => {

View File

@@ -22,7 +22,7 @@ msgstr ""
msgid "%{n} folders found" msgid "%{n} folders found"
msgstr "" msgstr ""
#: src/pages/labels.vue:392 #: src/pages/labels.vue:422
msgid "%{n} labels found" msgid "%{n} labels found"
msgstr "" msgstr ""
@@ -32,12 +32,12 @@ msgstr ""
msgid "%{n} people found" msgid "%{n} people found"
msgstr "" msgstr ""
#: src/pages/album/photos.vue:219 #: src/pages/album/photos.vue:222
#: src/pages/album/photos.vue:373 #: src/pages/album/photos.vue:376
#: src/pages/photos.vue:290 #: src/pages/photos.vue:291
#: src/pages/photos.vue:456 #: src/pages/photos.vue:457
#: src/share/photos.vue:223 #: src/share/photos.vue:227
#: src/share/photos.vue:370 #: src/share/photos.vue:374
msgid "%{n} pictures found" msgid "%{n} pictures found"
msgstr "" msgstr ""
@@ -57,7 +57,7 @@ msgstr ""
msgid "A click will copy it to your clipboard." msgid "A click will copy it to your clipboard."
msgstr "" msgstr ""
#: src/component/navigation.vue:423 #: src/component/navigation.vue:409
#: src/component/navigation.vue:27 #: src/component/navigation.vue:27
#: src/pages/about/about.vue:4 #: src/pages/about/about.vue:4
#: src/pages/about/about.vue:166 #: src/pages/about/about.vue:166
@@ -70,10 +70,10 @@ msgid "Abyss"
msgstr "" msgstr ""
#: src/component/navigation.vue:3 #: src/component/navigation.vue:3
#: src/component/navigation.vue:84 #: src/component/navigation.vue:88
#: src/dialog/share/upload.vue:107 #: src/dialog/share/upload.vue:107
#: src/model/account.js:98 #: src/model/account.js:98
#: src/model/user.js:136 #: src/model/user.js:139
#: src/pages/settings.vue:83 #: src/pages/settings.vue:83
msgid "Account" msgid "Account"
msgstr "" msgstr ""
@@ -115,9 +115,9 @@ msgstr ""
#: src/component/album/clipboard.vue:129 #: src/component/album/clipboard.vue:129
#: src/component/file/clipboard.vue:85 #: src/component/file/clipboard.vue:85
#: src/component/label/clipboard.vue:63 #: src/component/label/clipboard.vue:61
#: src/component/photo/clipboard.vue:180 #: src/component/photo/clipboard.vue:180
#: src/component/subject/clipboard.vue:85 #: src/component/subject/clipboard.vue:82
#: src/dialog/photo/album.vue:20 #: src/dialog/photo/album.vue:20
msgid "Add to album" msgid "Add to album"
msgstr "" msgstr ""
@@ -180,14 +180,10 @@ msgstr ""
#: src/app/routes.js:140 #: src/app/routes.js:140
#: src/app/routes.js:147 #: src/app/routes.js:147
#: src/component/navigation.vue:147 #: src/component/navigation.vue:147
#: src/component/navigation.vue:158 #: src/component/navigation.vue:157
#: src/component/navigation.vue:180 #: src/component/navigation.vue:524
#: src/component/navigation.vue:538
#: src/component/navigation.vue:6
#: src/component/navigation.vue:28
#: src/component/navigation.vue:4 #: src/component/navigation.vue:4
#: src/component/navigation.vue:619 #: src/component/navigation.vue:619
#: src/component/navigation.vue:732
#: src/share/albums.vue:4 #: src/share/albums.vue:4
msgid "Albums" msgid "Albums"
msgstr "" msgstr ""
@@ -201,7 +197,7 @@ msgstr ""
msgid "All %{n} albums loaded" msgid "All %{n} albums loaded"
msgstr "" msgstr ""
#: src/pages/labels.vue:246 #: src/pages/labels.vue:276
msgid "All %{n} labels loaded" msgid "All %{n} labels loaded"
msgstr "" msgstr ""
@@ -364,7 +360,7 @@ msgstr ""
msgid "Automatically creates albums of special moments, trips, and places." msgid "Automatically creates albums of special moments, trips, and places."
msgstr "" msgstr ""
#: src/component/navigation.vue:583 #: src/component/navigation.vue:569
#: src/dialog/sponsor.vue:7 #: src/dialog/sponsor.vue:7
#: src/pages/about/about.vue:33 #: src/pages/about/about.vue:33
#: src/pages/auth/login.vue:48 #: src/pages/auth/login.vue:48
@@ -422,8 +418,8 @@ msgstr ""
#: src/app/routes.js:153 #: src/app/routes.js:153
#: src/app/routes.js:160 #: src/app/routes.js:160
#: src/component/navigation.vue:267 #: src/component/navigation.vue:253
#: src/component/navigation.vue:1031 #: src/component/navigation.vue:987
msgid "Calendar" msgid "Calendar"
msgstr "" msgstr ""
@@ -438,9 +434,9 @@ msgstr ""
msgid "Camera Serial" msgid "Camera Serial"
msgstr "" msgstr ""
#: src/pages/album/photos.vue:225 #: src/pages/album/photos.vue:228
#: src/pages/photos.vue:296 #: src/pages/photos.vue:297
#: src/share/photos.vue:229 #: src/share/photos.vue:233
msgid "Can't load more, limit reached" msgid "Can't load more, limit reached"
msgstr "" msgstr ""
@@ -448,8 +444,8 @@ msgstr ""
#: src/common/clipboard.js:137 #: src/common/clipboard.js:137
#: src/pages/albums.vue:469 #: src/pages/albums.vue:469
#: src/pages/albums.vue:485 #: src/pages/albums.vue:485
#: src/pages/labels.vue:178 #: src/pages/labels.vue:204
#: src/pages/labels.vue:194 #: src/pages/labels.vue:224
#: src/pages/library/files.vue:193 #: src/pages/library/files.vue:193
#: src/pages/library/files.vue:209 #: src/pages/library/files.vue:209
#: src/pages/people/new.vue:215 #: src/pages/people/new.vue:215
@@ -568,13 +564,13 @@ msgid "Contact Us"
msgstr "" msgstr ""
#: src/pages/albums.vue:93 #: src/pages/albums.vue:93
#: src/pages/labels.vue:74 #: src/pages/labels.vue:77
#: src/pages/people/recognized.vue:90 #: src/pages/people/recognized.vue:90
msgid "Contains %{n} pictures." msgid "Contains %{n} pictures."
msgstr "" msgstr ""
#: src/pages/albums.vue:90 #: src/pages/albums.vue:90
#: src/pages/labels.vue:71 #: src/pages/labels.vue:74
#: src/pages/people/recognized.vue:87 #: src/pages/people/recognized.vue:87
msgid "Contains one picture." msgid "Contains one picture."
msgstr "" msgstr ""
@@ -663,7 +659,7 @@ msgid "Default Folder"
msgstr "" msgstr ""
#: src/component/album/clipboard.vue:153 #: src/component/album/clipboard.vue:153
#: src/component/label/clipboard.vue:85 #: src/component/label/clipboard.vue:82
#: src/component/photo/clipboard.vue:272 #: src/component/photo/clipboard.vue:272
#: src/dialog/account/remove.vue:18 #: src/dialog/account/remove.vue:18
#: src/dialog/album/delete.vue:18 #: src/dialog/album/delete.vue:18
@@ -745,10 +741,10 @@ msgstr ""
msgid "Disables reverse geocoding and maps." msgid "Disables reverse geocoding and maps."
msgstr "" msgstr ""
#: src/app/routes.js:390 #: src/app/routes.js:396
#: src/app/routes.js:397 #: src/app/routes.js:403
#: src/app/routes.js:404 #: src/app/routes.js:410
#: src/app/routes.js:411 #: src/app/routes.js:417
msgid "Discover" msgid "Discover"
msgstr "" msgstr ""
@@ -800,7 +796,7 @@ msgstr ""
#: src/component/file/clipboard.vue:62 #: src/component/file/clipboard.vue:62
#: src/component/photo-viewer.vue:78 #: src/component/photo-viewer.vue:78
#: src/component/photo/clipboard.vue:157 #: src/component/photo/clipboard.vue:157
#: src/component/subject/clipboard.vue:62 #: src/component/subject/clipboard.vue:60
#: src/dialog/photo/files.vue:32 #: src/dialog/photo/files.vue:32
#: src/dialog/photo/files.vue:29 #: src/dialog/photo/files.vue:29
#: src/pages/settings/general.vue:162 #: src/pages/settings/general.vue:162
@@ -821,17 +817,17 @@ msgstr ""
#: src/component/album/clipboard.vue:110 #: src/component/album/clipboard.vue:110
#: src/component/album/toolbar.vue:105 #: src/component/album/toolbar.vue:105
#: src/component/file/clipboard.vue:46 #: src/component/file/clipboard.vue:46
#: src/component/label/clipboard.vue:59 #: src/component/label/clipboard.vue:80
#: src/component/photo-viewer.vue:161 #: src/component/photo-viewer.vue:161
#: src/component/photo/cards.vue:133 #: src/component/photo/cards.vue:133
#: src/component/photo/clipboard.vue:210 #: src/component/photo/clipboard.vue:210
#: src/component/photo/list.vue:124 #: src/component/photo/list.vue:124
#: src/component/subject/clipboard.vue:46 #: src/component/subject/clipboard.vue:55
#: src/dialog/photo/files.vue:69 #: src/dialog/photo/files.vue:69
#: src/pages/library/files.vue:99 #: src/pages/library/files.vue:99
#: src/share/album/clipboard.vue:40 #: src/share/album/clipboard.vue:40
#: src/share/photo/clipboard.vue:45 #: src/share/photo/clipboard.vue:45
#: src/share/photos.vue:501 #: src/share/photos.vue:505
msgid "Downloading…" msgid "Downloading…"
msgstr "" msgstr ""
@@ -905,8 +901,8 @@ msgstr ""
msgid "Enables RAW converter presets. May reduce performance." msgid "Enables RAW converter presets. May reduce performance."
msgstr "" msgstr ""
#: src/app/routes.js:266 #: src/app/routes.js:272
#: src/component/navigation.vue:390 #: src/component/navigation.vue:376
msgid "Errors" msgid "Errors"
msgstr "" msgstr ""
@@ -977,7 +973,7 @@ msgstr ""
msgid "Failed updating link" msgid "Failed updating link"
msgstr "" msgstr ""
#: src/dialog/upload.vue:163 #: src/dialog/upload.vue:164
msgid "Failure while importing uploaded files" msgid "Failure while importing uploaded files"
msgstr "" msgstr ""
@@ -994,8 +990,8 @@ msgid "Favorite"
msgstr "" msgstr ""
#: src/app/routes.js:186 #: src/app/routes.js:186
#: src/component/navigation.vue:241 #: src/component/navigation.vue:227
#: src/component/navigation.vue:941 #: src/component/navigation.vue:897
msgid "Favorites" msgid "Favorites"
msgstr "" msgstr ""
@@ -1003,7 +999,7 @@ msgstr ""
msgid "Feature Request" msgid "Feature Request"
msgstr "" msgstr ""
#: src/component/navigation.vue:431 #: src/component/navigation.vue:417
#: src/component/navigation.vue:35 #: src/component/navigation.vue:35
msgid "Feedback" msgid "Feedback"
msgstr "" msgstr ""
@@ -1016,7 +1012,7 @@ msgstr ""
msgid "File" msgid "File"
msgstr "" msgstr ""
#: src/app/routes.js:253 #: src/app/routes.js:259
msgid "File Browser" msgid "File Browser"
msgstr "" msgstr ""
@@ -1025,7 +1021,7 @@ msgstr ""
msgid "Filename" msgid "Filename"
msgstr "" msgstr ""
#: src/component/navigation.vue:556 #: src/component/navigation.vue:542
#: src/dialog/photo/edit.vue:65 #: src/dialog/photo/edit.vue:65
#: src/dialog/photo/edit.vue:6 #: src/dialog/photo/edit.vue:6
#: src/dialog/photo/edit.vue:296 #: src/dialog/photo/edit.vue:296
@@ -1059,8 +1055,8 @@ msgstr ""
#: src/app/routes.js:166 #: src/app/routes.js:166
#: src/app/routes.js:173 #: src/app/routes.js:173
#: src/component/navigation.vue:327 #: src/component/navigation.vue:313
#: src/component/navigation.vue:1241 #: src/component/navigation.vue:1197
msgid "Folders" msgid "Folders"
msgstr "" msgstr ""
@@ -1137,11 +1133,11 @@ msgstr ""
msgid "Help & Support" msgid "Help & Support"
msgstr "" msgstr ""
#: src/component/navigation.vue:381 #: src/component/navigation.vue:367
msgid "Hidden" msgid "Hidden"
msgstr "" msgstr ""
#: src/app/routes.js:259 #: src/app/routes.js:265
msgid "Hidden Files" msgid "Hidden Files"
msgstr "" msgstr ""
@@ -1242,7 +1238,7 @@ msgstr ""
msgid "In case pictures you expect are missing, please rescan your library and wait until indexing has been completed." msgid "In case pictures you expect are missing, please rescan your library and wait until indexing has been completed."
msgstr "" msgstr ""
#: src/component/navigation.vue:562 #: src/component/navigation.vue:548
#: src/pages/library.vue:35 #: src/pages/library.vue:35
#: src/pages/settings/library.vue:6 #: src/pages/settings/library.vue:6
msgid "Index" msgid "Index"
@@ -1316,9 +1312,9 @@ msgstr ""
msgid "Label" msgid "Label"
msgstr "" msgstr ""
#: src/app/routes.js:272 #: src/app/routes.js:278
#: src/component/navigation.vue:314 #: src/component/navigation.vue:300
#: src/component/navigation.vue:1196 #: src/component/navigation.vue:1152
#: src/dialog/photo/edit.vue:39 #: src/dialog/photo/edit.vue:39
#: src/dialog/photo/edit.vue:6 #: src/dialog/photo/edit.vue:6
#: src/dialog/photo/edit.vue:195 #: src/dialog/photo/edit.vue:195
@@ -1326,7 +1322,7 @@ msgstr ""
msgid "Labels" msgid "Labels"
msgstr "" msgstr ""
#: src/component/label/clipboard.vue:45 #: src/component/label/clipboard.vue:62
msgid "Labels deleted" msgid "Labels deleted"
msgstr "" msgstr ""
@@ -1355,7 +1351,7 @@ msgstr ""
msgid "Learn more" msgid "Learn more"
msgstr "" msgstr ""
#: src/component/navigation.vue:587 #: src/component/navigation.vue:573
msgid "Legal Information" msgid "Legal Information"
msgstr "" msgstr ""
@@ -1363,19 +1359,19 @@ msgstr ""
msgid "Lens" msgid "Lens"
msgstr "" msgstr ""
#: src/app/routes.js:308 #: src/app/routes.js:314
#: src/app/routes.js:315 #: src/app/routes.js:321
#: src/app/routes.js:322 #: src/app/routes.js:328
#: src/component/navigation.vue:353 #: src/component/navigation.vue:339
#: src/component/navigation.vue:363 #: src/component/navigation.vue:349
#: src/component/navigation.vue:4 #: src/component/navigation.vue:4
#: src/component/navigation.vue:1333 #: src/component/navigation.vue:1289
#: src/pages/settings.vue:47 #: src/pages/settings.vue:47
#: src/pages/settings/general.vue:404 #: src/pages/settings/general.vue:404
msgid "Library" msgid "Library"
msgstr "" msgstr ""
#: src/component/navigation.vue:439 #: src/component/navigation.vue:425
#: src/component/navigation.vue:43 #: src/component/navigation.vue:43
#: src/dialog/photo/details.vue:540 #: src/dialog/photo/details.vue:540
#: src/pages/about/license.vue:4 #: src/pages/about/license.vue:4
@@ -1408,7 +1404,7 @@ msgid "List"
msgstr "" msgstr ""
#: src/app/routes.js:193 #: src/app/routes.js:193
#: src/component/navigation.vue:214 #: src/component/navigation.vue:200
#: src/component/photo/cards.vue:292 #: src/component/photo/cards.vue:292
#: src/component/photo/list.vue:182 #: src/component/photo/list.vue:182
#: src/component/photo/mosaic.vue:215 #: src/component/photo/mosaic.vue:215
@@ -1436,20 +1432,20 @@ msgstr ""
msgid "Log messages appear here whenever PhotoPrism comes across broken files, or there are other potential issues." msgid "Log messages appear here whenever PhotoPrism comes across broken files, or there are other potential issues."
msgstr "" msgstr ""
#: src/component/navigation.vue:453 #: src/component/navigation.vue:439
#: src/component/navigation.vue:1669 #: src/component/navigation.vue:1625
#: src/component/navigation.vue:1890 #: src/component/navigation.vue:1846
msgid "Login" msgid "Login"
msgstr "" msgstr ""
#: src/component/navigation.vue:500 #: src/component/navigation.vue:486
#: src/component/navigation.vue:1779 #: src/component/navigation.vue:1735
#: src/component/navigation.vue:1810 #: src/component/navigation.vue:1766
#: src/component/navigation.vue:1861 #: src/component/navigation.vue:1817
msgid "Logout" msgid "Logout"
msgstr "" msgstr ""
#: src/component/navigation.vue:1908 #: src/component/navigation.vue:1864
#: src/pages/library.vue:58 #: src/pages/library.vue:58
#: src/pages/settings/general.vue:426 #: src/pages/settings/general.vue:426
msgid "Logs" msgid "Logs"
@@ -1508,8 +1504,8 @@ msgstr ""
#: src/app/routes.js:127 #: src/app/routes.js:127
#: src/app/routes.js:134 #: src/app/routes.js:134
#: src/component/navigation.vue:254 #: src/component/navigation.vue:240
#: src/component/navigation.vue:986 #: src/component/navigation.vue:942
#: src/pages/settings/general.vue:360 #: src/pages/settings/general.vue:360
msgid "Moments" msgid "Moments"
msgstr "" msgstr ""
@@ -1527,9 +1523,9 @@ msgstr ""
msgid "Moonlight" msgid "Moonlight"
msgstr "" msgstr ""
#: src/pages/album/photos.vue:376 #: src/pages/album/photos.vue:379
#: src/pages/photos.vue:459 #: src/pages/photos.vue:460
#: src/share/photos.vue:373 #: src/share/photos.vue:377
msgid "More than %{n} pictures found" msgid "More than %{n} pictures found"
msgstr "" msgstr ""
@@ -1538,7 +1534,7 @@ msgstr ""
msgid "More than 20 albums found" msgid "More than 20 albums found"
msgstr "" msgstr ""
#: src/pages/labels.vue:395 #: src/pages/labels.vue:425
msgid "More than 20 labels found" msgid "More than 20 labels found"
msgstr "" msgstr ""
@@ -1578,7 +1574,7 @@ msgstr ""
#: src/pages/about/feedback.vue:171 #: src/pages/about/feedback.vue:171
#: src/pages/auth/login.vue:77 #: src/pages/auth/login.vue:77
#: src/pages/auth/login.vue:81 #: src/pages/auth/login.vue:81
#: src/pages/labels.vue:327 #: src/pages/labels.vue:339
#: src/pages/people/new.vue:52 #: src/pages/people/new.vue:52
#: src/pages/people/new.vue:299 #: src/pages/people/new.vue:299
#: src/pages/people/recognized.vue:396 #: src/pages/people/recognized.vue:396
@@ -1589,7 +1585,7 @@ msgstr ""
#: src/dialog/album/edit.vue:28 #: src/dialog/album/edit.vue:28
#: src/dialog/photo/labels.vue:25 #: src/dialog/photo/labels.vue:25
#: src/dialog/photo/people.vue:24 #: src/dialog/photo/people.vue:24
#: src/pages/labels.vue:37 #: src/pages/labels.vue:45
#: src/pages/library/files.vue:40 #: src/pages/library/files.vue:40
#: src/pages/people/new.vue:46 #: src/pages/people/new.vue:46
#: src/pages/people/recognized.vue:45 #: src/pages/people/recognized.vue:45
@@ -1635,7 +1631,7 @@ msgstr ""
#: src/dialog/photo/labels.vue:28 #: src/dialog/photo/labels.vue:28
#: src/pages/labels.vue:31 #: src/pages/labels.vue:31
#: src/pages/labels.vue:388 #: src/pages/labels.vue:418
msgid "No labels found" msgid "No labels found"
msgstr "" msgstr ""
@@ -1654,12 +1650,14 @@ msgstr ""
#: src/component/photo/list.vue:8 #: src/component/photo/list.vue:8
#: src/component/photo/mosaic.vue:8 #: src/component/photo/mosaic.vue:8
#: src/component/photo/mosaic.vue:6 #: src/component/photo/mosaic.vue:6
#: src/pages/album/photos.vue:369 #: src/pages/album/photos.vue:372
#: src/pages/library/files.vue:34 #: src/pages/library/files.vue:34
#: src/pages/photos.vue:452 #: src/pages/photos.vue:453
#: src/pages/places.vue:207 #: src/pages/places.vue:217
#: src/pages/places.vue:267 #: src/pages/places.vue:279
#: src/share/photos.vue:366 #: src/share/photos.vue:370
#: src/share/places.vue:207
#: src/share/places.vue:267
msgid "No pictures found" msgid "No pictures found"
msgstr "" msgstr ""
@@ -1740,8 +1738,8 @@ msgstr ""
msgid "Nothing to see here yet." msgid "Nothing to see here yet."
msgstr "" msgstr ""
#: src/component/navigation.vue:469 #: src/component/navigation.vue:455
#: src/component/navigation.vue:1714 #: src/component/navigation.vue:1670
#: src/options/options.js:259 #: src/options/options.js:259
msgid "Offline" msgid "Offline"
msgstr "" msgstr ""
@@ -1777,7 +1775,7 @@ msgstr ""
msgid "One folder found" msgid "One folder found"
msgstr "" msgstr ""
#: src/pages/labels.vue:390 #: src/pages/labels.vue:420
msgid "One label found" msgid "One label found"
msgstr "" msgstr ""
@@ -1787,9 +1785,9 @@ msgstr ""
msgid "One person found" msgid "One person found"
msgstr "" msgstr ""
#: src/pages/album/photos.vue:371 #: src/pages/album/photos.vue:374
#: src/pages/photos.vue:454 #: src/pages/photos.vue:455
#: src/share/photos.vue:368 #: src/share/photos.vue:372
msgid "One picture found" msgid "One picture found"
msgstr "" msgstr ""
@@ -1824,7 +1822,7 @@ msgstr ""
msgid "Original Name" msgid "Original Name"
msgstr "" msgstr ""
#: src/component/navigation.vue:372 #: src/component/navigation.vue:358
#: src/dialog/account/edit.vue:104 #: src/dialog/account/edit.vue:104
#: src/model/file.js:194 #: src/model/file.js:194
#: src/pages/library/files.vue:6 #: src/pages/library/files.vue:6
@@ -1855,8 +1853,8 @@ msgstr ""
#: src/dialog/account/add.vue:102 #: src/dialog/account/add.vue:102
#: src/dialog/account/edit.vue:453 #: src/dialog/account/edit.vue:453
#: src/dialog/share.vue:24 #: src/dialog/share.vue:24
#: src/pages/auth/login.vue:97 #: src/pages/auth/login.vue:98
#: src/pages/auth/login.vue:99 #: src/pages/auth/login.vue:100
msgid "Password" msgid "Password"
msgstr "" msgstr ""
@@ -1864,11 +1862,11 @@ msgstr ""
msgid "Password changed" msgid "Password changed"
msgstr "" msgstr ""
#: src/app/routes.js:278 #: src/app/routes.js:284
#: src/app/routes.js:302 #: src/app/routes.js:308
#: src/component/navigation.vue:228 #: src/component/navigation.vue:214
#: src/component/navigation.vue:544 #: src/component/navigation.vue:530
#: src/component/navigation.vue:896 #: src/component/navigation.vue:852
#: src/dialog/photo/edit.vue:52 #: src/dialog/photo/edit.vue:52
#: src/dialog/photo/edit.vue:6 #: src/dialog/photo/edit.vue:6
#: src/dialog/photo/edit.vue:246 #: src/dialog/photo/edit.vue:246
@@ -1919,12 +1917,13 @@ msgstr ""
#: src/app/routes.js:228 #: src/app/routes.js:228
#: src/app/routes.js:234 #: src/app/routes.js:234
#: src/app/routes.js:240 #: src/app/routes.js:240
#: src/app/routes.js:247 #: src/app/routes.js:246
#: src/component/navigation.vue:280 #: src/app/routes.js:253
#: src/component/navigation.vue:290 #: src/component/navigation.vue:266
#: src/component/navigation.vue:550 #: src/component/navigation.vue:276
#: src/component/navigation.vue:536
#: src/component/navigation.vue:4 #: src/component/navigation.vue:4
#: src/component/navigation.vue:1078 #: src/component/navigation.vue:1034
#: src/pages/settings/general.vue:108 #: src/pages/settings/general.vue:108
#: src/pages/settings/general.vue:450 #: src/pages/settings/general.vue:450
msgid "Places" msgid "Places"
@@ -1978,8 +1977,8 @@ msgid "Primary"
msgstr "" msgstr ""
#: src/app/routes.js:214 #: src/app/routes.js:214
#: src/component/navigation.vue:340 #: src/component/navigation.vue:326
#: src/component/navigation.vue:1286 #: src/component/navigation.vue:1242
#: src/dialog/photo/info.vue:102 #: src/dialog/photo/info.vue:102
#: src/pages/settings/general.vue:272 #: src/pages/settings/general.vue:272
msgid "Private" msgid "Private"
@@ -2070,11 +2069,11 @@ msgid "Red"
msgstr "" msgstr ""
#: src/component/album/toolbar.vue:45 #: src/component/album/toolbar.vue:45
#: src/component/navigation.vue:1875 #: src/component/navigation.vue:1831
#: src/component/photo/toolbar.vue:54 #: src/component/photo/toolbar.vue:54
#: src/dialog/reload.vue:15 #: src/dialog/reload.vue:15
#: src/pages/albums.vue:123 #: src/pages/albums.vue:123
#: src/pages/labels.vue:81 #: src/pages/labels.vue:85
#: src/pages/library/errors.vue:70 #: src/pages/library/errors.vue:70
#: src/pages/library/files.vue:91 #: src/pages/library/files.vue:91
#: src/pages/people/new.vue:57 #: src/pages/people/new.vue:57
@@ -2082,7 +2081,7 @@ msgstr ""
msgid "Reload" msgid "Reload"
msgstr "" msgstr ""
#: src/component/navigation.vue:115 #: src/component/navigation.vue:119
#: src/dialog/reload.vue:26 #: src/dialog/reload.vue:26
#: src/pages/settings/general.vue:101 #: src/pages/settings/general.vue:101
#: src/pages/settings/library.vue:46 #: src/pages/settings/library.vue:46
@@ -2157,15 +2156,16 @@ msgstr ""
#: src/component/navigation.vue:65 #: src/component/navigation.vue:65
#: src/component/navigation.vue:75 #: src/component/navigation.vue:75
#: src/component/navigation.vue:532 #: src/component/navigation.vue:518
#: src/component/navigation.vue:4 #: src/component/navigation.vue:4
#: src/component/navigation.vue:330 #: src/component/navigation.vue:330
#: src/component/photo/toolbar.vue:44 #: src/component/photo/toolbar.vue:44
#: src/pages/albums.vue:96 #: src/pages/albums.vue:96
#: src/pages/labels.vue:68 #: src/pages/labels.vue:72
#: src/pages/library/errors.vue:59 #: src/pages/library/errors.vue:59
#: src/pages/people/recognized.vue:78 #: src/pages/people/recognized.vue:78
#: src/pages/places.vue:34 #: src/pages/places.vue:38
#: src/share/places.vue:34
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@@ -2223,18 +2223,18 @@ msgstr ""
msgid "Service URL" msgid "Service URL"
msgstr "" msgstr ""
#: src/app/routes.js:330 #: src/app/routes.js:336
#: src/app/routes.js:342 #: src/app/routes.js:348
#: src/app/routes.js:354 #: src/app/routes.js:360
#: src/app/routes.js:366 #: src/app/routes.js:372
#: src/app/routes.js:378 #: src/app/routes.js:384
#: src/component/navigation.vue:404 #: src/component/navigation.vue:390
#: src/component/navigation.vue:414 #: src/component/navigation.vue:400
#: src/component/navigation.vue:8 #: src/component/navigation.vue:8
#: src/component/navigation.vue:18 #: src/component/navigation.vue:18
#: src/component/navigation.vue:4 #: src/component/navigation.vue:4
#: src/component/navigation.vue:1507 #: src/component/navigation.vue:1463
#: src/component/navigation.vue:1926 #: src/component/navigation.vue:1882
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""
@@ -2281,7 +2281,7 @@ msgstr ""
msgid "Show hidden" msgid "Show hidden"
msgstr "" msgstr ""
#: src/pages/labels.vue:116 #: src/pages/labels.vue:120
msgid "Show less" msgid "Show less"
msgstr "" msgstr ""
@@ -2289,7 +2289,7 @@ msgstr ""
msgid "Show Library in navigation menu." msgid "Show Library in navigation menu."
msgstr "" msgstr ""
#: src/pages/labels.vue:99 #: src/pages/labels.vue:103
msgid "Show more" msgid "Show more"
msgstr "" msgstr ""
@@ -2381,7 +2381,7 @@ msgstr ""
msgid "Start/Stop Slideshow" msgid "Start/Stop Slideshow"
msgstr "" msgstr ""
#: src/component/navigation.vue:300 #: src/component/navigation.vue:286
msgid "States" msgid "States"
msgstr "" msgstr ""
@@ -2419,7 +2419,7 @@ msgstr ""
msgid "Support for additional services, like Google Drive, will be added over time." msgid "Support for additional services, like Google Drive, will be added over time."
msgstr "" msgstr ""
#: src/component/navigation.vue:568 #: src/component/navigation.vue:554
#: src/pages/settings.vue:71 #: src/pages/settings.vue:71
#: src/pages/settings/sync.vue:27 #: src/pages/settings/sync.vue:27
msgid "Sync" msgid "Sync"
@@ -2576,14 +2576,13 @@ msgstr ""
msgid "Unknown" msgid "Unknown"
msgstr "" msgstr ""
#: src/component/navigation.vue:76 #: src/component/navigation.vue:80
#: src/model/user.js:122 #: src/model/user.js:125
msgid "Unregistered" msgid "Unregistered"
msgstr "" msgstr ""
#: src/app/routes.js:179 #: src/app/routes.js:179
#: src/component/navigation.vue:168 #: src/component/navigation.vue:167
#: src/component/navigation.vue:16
msgid "Unsorted" msgid "Unsorted"
msgstr "" msgstr ""
@@ -2619,7 +2618,7 @@ msgid "Updating stacks"
msgstr "" msgstr ""
#: src/component/album/toolbar.vue:170 #: src/component/album/toolbar.vue:170
#: src/component/navigation.vue:1944 #: src/component/navigation.vue:1900
#: src/component/photo/toolbar.vue:122 #: src/component/photo/toolbar.vue:122
#: src/dialog/share/upload.vue:35 #: src/dialog/share/upload.vue:35
#: src/dialog/upload.vue:8 #: src/dialog/upload.vue:8
@@ -2631,7 +2630,7 @@ msgstr ""
msgid "Upload" msgid "Upload"
msgstr "" msgstr ""
#: src/dialog/upload.vue:159 #: src/dialog/upload.vue:160
msgid "Upload complete" msgid "Upload complete"
msgstr "" msgstr ""
@@ -2655,9 +2654,9 @@ msgstr ""
msgid "Uploading %{n} of %{t}…" msgid "Uploading %{n} of %{t}…"
msgstr "" msgstr ""
#: src/dialog/upload.vue:59 #: src/dialog/upload.vue:60
#: src/dialog/upload.vue:67 #: src/dialog/upload.vue:68
#: src/dialog/upload.vue:112 #: src/dialog/upload.vue:113
msgid "Uploading photos…" msgid "Uploading photos…"
msgstr "" msgstr ""
@@ -2673,12 +2672,12 @@ msgstr ""
msgid "Use Presets" msgid "Use Presets"
msgstr "" msgstr ""
#: src/model/user.js:173 #: src/model/user.js:176
#: src/options/options.js:411 #: src/options/options.js:411
msgid "User" msgid "User"
msgstr "" msgstr ""
#: src/component/navigation.vue:579 #: src/component/navigation.vue:565
#: src/pages/about/about.vue:45 #: src/pages/about/about.vue:45
msgid "User Guide" msgid "User Guide"
msgstr "" msgstr ""
@@ -2713,10 +2712,10 @@ msgid "Video"
msgstr "" msgstr ""
#: src/app/routes.js:200 #: src/app/routes.js:200
#: src/component/navigation.vue:194 #: src/component/navigation.vue:180
#: src/component/navigation.vue:204 #: src/component/navigation.vue:190
#: src/component/navigation.vue:4 #: src/component/navigation.vue:4
#: src/component/navigation.vue:780 #: src/component/navigation.vue:736
msgid "Videos" msgid "Videos"
msgstr "" msgstr ""
@@ -2810,12 +2809,12 @@ msgid "you are welcome to join us on Reddit"
msgstr "" msgstr ""
#: src/component/album/clipboard.vue:106 #: src/component/album/clipboard.vue:106
#: src/component/subject/clipboard.vue:42 #: src/component/subject/clipboard.vue:51
#: src/share/album/clipboard.vue:36 #: src/share/album/clipboard.vue:36
msgid "You can only download one album" msgid "You can only download one album"
msgstr "" msgstr ""
#: src/component/label/clipboard.vue:50 #: src/component/label/clipboard.vue:71
msgid "You can only download one label" msgid "You can only download one label"
msgstr "" msgstr ""

View File

@@ -43,8 +43,10 @@ export class User extends RestModel {
Role: "", Role: "",
Attr: "", Attr: "",
SuperAdmin: false, SuperAdmin: false,
WebLogin: false, CanLogin: false,
WebDAV: false, BasePath: "",
UploadPath: "",
CanSync: false,
CanInvite: false, CanInvite: false,
Thumb: "", Thumb: "",
ThumbSrc: "", ThumbSrc: "",
@@ -59,6 +61,7 @@ export class User extends RestModel {
ImportPath: "", ImportPath: "",
ImportMove: 0, ImportMove: 0,
UploadPath: "", UploadPath: "",
DefaultPage: "",
CreatedAt: "", CreatedAt: "",
UpdatedAt: "", UpdatedAt: "",
}, },
@@ -119,7 +122,7 @@ export class User extends RestModel {
return T(Util.capitalize(this.Role)); return T(Util.capitalize(this.Role));
} }
return this.$gettext("Unregistered"); return $gettext("Unregistered");
} }
getAccountInfo() { getAccountInfo() {
@@ -133,7 +136,7 @@ export class User extends RestModel {
return this.Name; return this.Name;
} }
return this.$gettext("Account"); return $gettext("Account");
} }
getEntityName() { getEntityName() {

View File

@@ -80,6 +80,7 @@ export default {
isShared: this.$config.deny("photos", "manage"), isShared: this.$config.deny("photos", "manage"),
canEdit: this.$config.allow("photos", "update") && this.$config.feature("edit"), canEdit: this.$config.allow("photos", "update") && this.$config.feature("edit"),
hasPlaces: this.$config.allow("places", "view") && this.$config.feature("places"), hasPlaces: this.$config.allow("places", "view") && this.$config.feature("places"),
canSearchPlaces: this.$config.allow("places", "search") && this.$config.feature("places"),
subscriptions: [], subscriptions: [],
listen: false, listen: false,
dirty: false, dirty: false,
@@ -171,12 +172,14 @@ export default {
const photo = this.results[index]; const photo = this.results[index];
if (photo.CellID && photo.CellID !== "zz") { if (photo && photo.CellID && photo.CellID !== "zz") {
if (this.canSearchPlaces) {
this.$router.push({name: "place", params: {q: photo.CellID}}); this.$router.push({name: "place", params: {q: photo.CellID}});
} else if (photo.Country && photo.Country !== "zz") {
this.$router.push({name: "place", params: {q: "country:" + photo.Country}});
} else { } else {
this.$notify.warn("unknown location"); this.$router.push({name: "album_place", params: {album: this.uid, q: photo.CellID}});
}
} else {
this.$router.push({name: "album_place", params: {album: this.uid, q: ""}});
} }
}, },
editPhoto(index) { editPhoto(index) {

View File

@@ -36,12 +36,12 @@
<v-icon>refresh</v-icon> <v-icon>refresh</v-icon>
</v-btn> </v-btn>
<v-btn v-if="!$config.values.readonly && $config.feature('upload')" icon class="hidden-sm-and-down action-upload" <v-btn v-if="canUpload" icon class="hidden-sm-and-down action-upload"
:title="$gettext('Upload')" @click.stop="showUpload()"> :title="$gettext('Upload')" @click.stop="showUpload()">
<v-icon>cloud_upload</v-icon> <v-icon>cloud_upload</v-icon>
</v-btn> </v-btn>
<v-btn v-if="staticFilter.type === 'album'" icon class="action-add" :title="$gettext('Add Album')" <v-btn v-if="canManage && staticFilter.type === 'album'" icon class="action-add" :title="$gettext('Add Album')"
@click.prevent="create()"> @click.prevent="create()">
<v-icon>add</v-icon> <v-icon>add</v-icon>
</v-btn> </v-btn>
@@ -245,7 +245,7 @@ export default {
} }
return { return {
canUpload: features.upload, canUpload: this.$config.allow("files", "upload") && features.upload,
canShare: this.$config.allow("albums", "share") && features.share, canShare: this.$config.allow("albums", "share") && features.share,
canManage: this.$config.allow("albums", "manage"), canManage: this.$config.allow("albums", "manage"),
canEdit: this.$config.allow("albums", "update"), canEdit: this.$config.allow("albums", "update"),

View File

@@ -23,6 +23,7 @@
:color="colors.accent" :color="colors.accent"
:placeholder="$gettext('Name')" :placeholder="$gettext('Name')"
prepend-icon="person" prepend-icon="person"
@keyup.enter.native="login"
></v-text-field> ></v-text-field>
<v-text-field <v-text-field
v-model="password" v-model="password"

View File

@@ -36,7 +36,7 @@
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear> <v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container> </v-container>
<v-container v-else fluid class="pa-0"> <v-container v-else fluid class="pa-0">
<p-label-clipboard :refresh="refresh" :selection="selection" <p-label-clipboard v-if="canSelect" :refresh="refresh" :selection="selection"
:clear-selection="clearSelection"></p-label-clipboard> :clear-selection="clearSelection"></p-label-clipboard>
<p-scroll-top></p-scroll-top> <p-scroll-top></p-scroll-top>
@@ -81,7 +81,7 @@
@mousedown.stop.prevent="input.mouseDown($event, index)" @mousedown.stop.prevent="input.mouseDown($event, index)"
@click.stop.prevent="onClick($event, index)" @click.stop.prevent="onClick($event, index)"
> >
<v-btn :ripple="false" <v-btn v-if="canSelect" :ripple="false"
icon flat absolute icon flat absolute
class="input-select" class="input-select"
@touchstart.stop.prevent="input.touchStart($event, index)" @touchstart.stop.prevent="input.touchStart($event, index)"
@@ -105,7 +105,7 @@
</v-img> </v-img>
<v-card-title primary-title class="pa-3 card-details" style="user-select: none;" @click.stop.prevent=""> <v-card-title primary-title class="pa-3 card-details" style="user-select: none;" @click.stop.prevent="">
<v-edit-dialog <v-edit-dialog v-if="canManage"
:return-value.sync="label.Name" :return-value.sync="label.Name"
lazy lazy
class="inline-edit" class="inline-edit"
@@ -128,6 +128,9 @@
></v-text-field> ></v-text-field>
</template> </template>
</v-edit-dialog> </v-edit-dialog>
<span v-else class="body-2 ma-0">
{{ label.Name }}
</span>
</v-card-title> </v-card-title>
<v-card-text primary-title class="pb-2 pt-0 card-details" style="user-select: none;" <v-card-text primary-title class="pb-2 pt-0 card-details" style="user-select: none;"
@@ -160,7 +163,10 @@ import {Input, InputInvalid, ClickShort, ClickLong} from "common/input";
export default { export default {
name: 'PPageLabels', name: 'PPageLabels',
props: { props: {
staticFilter: Object staticFilter: {
type: Object,
default: () => {},
},
}, },
data() { data() {
const query = this.$route.query; const query = this.$route.query;
@@ -168,7 +174,12 @@ export default {
const q = query['q'] ? query['q'] : ''; const q = query['q'] ? query['q'] : '';
const all = query['all'] ? query['all'] : ''; const all = query['all'] ? query['all'] : '';
const canManage = this.$config.allow("labels", "manage");
const canAddAlbums = this.$config.allow("albums", "create") && this.$config.feature("albums");
return { return {
canManage: canManage,
canSelect: canManage || canAddAlbums,
view: 'all', view: 'all',
config: this.$config.values, config: this.$config.values,
subscriptions: [], subscriptions: [],
@@ -231,6 +242,10 @@ export default {
window.localStorage.setItem("labels_offset", offset); window.localStorage.setItem("labels_offset", offset);
}, },
toggleLike(ev, index) { toggleLike(ev, index) {
if (!this.canManage) {
return;
}
const inputType = this.input.eval(ev, index); const inputType = this.input.eval(ev, index);
if (inputType !== ClickShort) { if (inputType !== ClickShort) {
@@ -246,7 +261,9 @@ export default {
label.toggleLike(); label.toggleLike();
}, },
selectRange(rangeEnd, models) { selectRange(rangeEnd, models) {
if (!models || !models[rangeEnd] || !(models[rangeEnd] instanceof RestModel)) { if (!this.canSelect) {
return;
} else if (!models || !models[rangeEnd] || !(models[rangeEnd] instanceof RestModel)) {
console.warn("selectRange() - invalid arguments:", rangeEnd, models); console.warn("selectRange() - invalid arguments:", rangeEnd, models);
return; return;
} }
@@ -271,6 +288,10 @@ export default {
return (rangeEnd - rangeStart) + 1; return (rangeEnd - rangeStart) + 1;
}, },
onSelect(ev, index) { onSelect(ev, index) {
if (!this.canSelect) {
return;
}
const inputType = this.input.eval(ev, index); const inputType = this.input.eval(ev, index);
if (inputType !== ClickShort) { if (inputType !== ClickShort) {
@@ -302,6 +323,10 @@ export default {
} }
}, },
onContextMenu(ev, index) { onContextMenu(ev, index) {
if (!this.canSelect) {
return;
}
if (this.$isMobile) { if (this.$isMobile) {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
@@ -312,6 +337,10 @@ export default {
} }
}, },
onSave(label) { onSave(label) {
if (!this.canManage) {
return;
}
label.update(); label.update();
}, },
showAll() { showAll() {
@@ -336,6 +365,10 @@ export default {
} }
}, },
toggleSelection(uid) { toggleSelection(uid) {
if (!this.canSelect) {
return;
}
const pos = this.selection.indexOf(uid); const pos = this.selection.indexOf(uid);
if (pos !== -1) { if (pos !== -1) {

View File

@@ -103,6 +103,7 @@ export default {
isShared: this.$config.deny("photos", "manage"), isShared: this.$config.deny("photos", "manage"),
canEdit: this.$config.allow("photos", "update") && features.edit, canEdit: this.$config.allow("photos", "update") && features.edit,
hasPlaces: this.$config.allow("places", "view") && features.places, hasPlaces: this.$config.allow("places", "view") && features.places,
canSearchPlaces: this.$config.allow("places", "search") && features.places,
subscriptions: [], subscriptions: [],
listen: false, listen: false,
dirty: false, dirty: false,
@@ -233,7 +234,7 @@ export default {
return "newest"; return "newest";
}, },
openLocation(index) { openLocation(index) {
if (!this.hasPlaces) { if (!this.canSearchPlaces) {
return; return;
} }

View File

@@ -1,7 +1,7 @@
<template> <template>
<v-container fluid fill-height :class="$config.aclClasses('places')" class="pa-0 p-page p-page-places"> <v-container fluid fill-height :class="$config.aclClasses('places')" class="pa-0 p-page p-page-places">
<div id="map" style="width: 100%; height: 100%;"> <div id="map" style="width: 100%; height: 100%;">
<div class="map-control"> <div v-if="canSearch" class="map-control">
<div class="maplibregl-ctrl maplibregl-ctrl-group"> <div class="maplibregl-ctrl maplibregl-ctrl-group">
<v-text-field v-model.lazy.trim="filter.q" <v-text-field v-model.lazy.trim="filter.q"
solo hide-details clearable flat single-line validate-on-blur solo hide-details clearable flat single-line validate-on-blur
@@ -37,6 +37,7 @@ export default {
}, },
data() { data() {
return { return {
canSearch: this.$config.allow("places", "search"),
initialized: false, initialized: false,
map: null, map: null,
markers: {}, markers: {},
@@ -48,7 +49,7 @@ export default {
options: {}, options: {},
mapFont: ["Open Sans Regular"], mapFont: ["Open Sans Regular"],
result: {}, result: {},
filter: {q: this.query()}, filter: {q: this.query(), album: this.album()},
lastFilter: {}, lastFilter: {},
config: this.$config.values, config: this.$config.values,
settings: this.$config.values.settings.maps, settings: this.$config.values.settings.maps,
@@ -57,6 +58,7 @@ export default {
watch: { watch: {
'$route'() { '$route'() {
this.filter.q = this.query(); this.filter.q = this.query();
this.filter.album = this.album();
this.lastFilter = {}; this.lastFilter = {};
this.search(); this.search();
@@ -75,6 +77,7 @@ export default {
const s = this.$config.values.settings.maps; const s = this.$config.values.settings.maps;
const filter = { const filter = {
q: this.query(), q: this.query(),
album: this.album(),
}; };
let mapKey = ""; let mapKey = "";
@@ -205,6 +208,9 @@ export default {
query: function () { query: function () {
return this.$route.params.q ? this.$route.params.q : ''; return this.$route.params.q ? this.$route.params.q : '';
}, },
album: function () {
return this.$route.params.album ? this.$route.params.album : '';
},
openPhoto(uid) { openPhoto(uid) {
// Abort if uid is empty or results aren't loaded. // Abort if uid is empty or results aren't loaded.
if (!uid || this.loading || !this.result || !this.result.features || this.result.features.length === 0) { if (!uid || this.loading || !this.result || !this.result.features || this.result.features.length === 0) {
@@ -219,6 +225,10 @@ export default {
}, },
}; };
if (this.filter.album) {
options.params.album = this.filter.album;
}
this.loading = true; this.loading = true;
// Perform get request to find nearby photos. // Perform get request to find nearby photos.
@@ -246,7 +256,9 @@ export default {
if (this.loading) return; if (this.loading) return;
if (this.query() !== this.filter.q) { if (this.query() !== this.filter.q) {
if (this.filter.q) { if (this.filter.album) {
this.$router.replace({name: "album_place", params: {album: this.filter.album, q: this.filter.q}});
} else if (this.filter.q) {
this.$router.replace({name: "place", params: {q: this.filter.q}}); this.$router.replace({name: "place", params: {q: this.filter.q}});
} else { } else {
this.$router.replace({name: "places"}); this.$router.replace({name: "places"});

View File

@@ -121,6 +121,8 @@ export default {
const batchSize = Photo.batchSize(); const batchSize = Photo.batchSize();
return { return {
hasPlaces: this.$config.allow("places", "view") && this.$config.feature("places"),
canSearchPlaces: this.$config.allow("places", "search") && this.$config.feature("places"),
subscriptions: [], subscriptions: [],
listen: false, listen: false,
dirty: false, dirty: false,
@@ -219,14 +221,16 @@ export default {
return 'cards'; return 'cards';
}, },
openLocation(index) { openLocation(index) {
if (!this.hasPlaces) {
return;
}
const photo = this.results[index]; const photo = this.results[index];
if (photo.CellID && photo.CellID !== "zz") { if (photo && photo.CellID && photo.CellID !== "zz") {
this.$router.push({name: "place", params: {q: photo.CellID}}); this.$router.push({name: "album_place", params: {album: this.uid, q: photo.CellID}});
} else if (photo.Country && photo.Country !== "zz") {
this.$router.push({name: "place", params: {q: "country:" + photo.Country}});
} else { } else {
this.$notify.warn("unknown location"); this.$router.push({name: "album_place", params: {album: this.uid, q: ""}});
} }
}, },
editPhoto(index) { editPhoto(index) {

View File

@@ -0,0 +1,456 @@
<template>
<v-container fluid fill-height :class="$config.aclClasses('places')" class="pa-0 p-page p-page-places">
<div id="map" style="width: 100%; height: 100%;">
<div class="map-control">
<div class="maplibregl-ctrl maplibregl-ctrl-group">
<v-text-field v-model.lazy.trim="filter.q"
solo hide-details clearable flat single-line validate-on-blur
class="input-search pa-0 ma-0"
:label="$gettext('Search')"
prepend-inner-icon="search"
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
color="secondary-dark"
@click:clear="clearQuery"
@keyup.enter.native="formChange"
></v-text-field>
</div>
</div>
</div>
</v-container>
</template>
<script>
import maplibregl from "maplibre-gl";
import Api from "common/api";
import Thumb from "model/thumb";
export default {
name: 'PPagePlaces',
props: {
staticFilter: {
type: Object,
default: () => {
},
},
},
data() {
return {
initialized: false,
map: null,
markers: {},
markersOnScreen: {},
loading: false,
url: "",
attribution: '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>',
maxCount: 500000,
options: {},
mapFont: ["Open Sans Regular"],
result: {},
filter: {q: this.query()},
lastFilter: {},
config: this.$config.values,
settings: this.$config.values.settings.maps,
};
},
watch: {
'$route'() {
this.filter.q = this.query();
this.lastFilter = {};
this.search();
}
},
mounted() {
this.$scrollbar.hide();
this.configureMap().then(() => this.renderMap());
},
destroyed() {
this.$scrollbar.show();
},
methods: {
configureMap() {
return this.$config.load().finally(() => {
const s = this.$config.values.settings.maps;
const filter = {
q: this.query(),
};
let mapKey = "";
if (this.$config.has("mapKey")) {
// Remove non-alphanumeric characters from key.
mapKey = this.$config.get("mapKey").replace(/[^a-z0-9]/gi, '');
}
const settings = this.$config.settings();
if (settings && settings.features.private) {
filter.public = "true";
}
if (settings && settings.features.review && (!this.staticFilter || !("quality" in this.staticFilter))) {
filter.quality = "3";
}
let mapOptions = {
container: "map",
style: "https://api.maptiler.com/maps/" + s.style + "/style.json?key=" + mapKey,
glyphs: "https://api.maptiler.com/fonts/{fontstack}/{range}.pbf?key=" + mapKey,
attributionControl: true,
customAttribution: this.attribution,
zoom: 0,
};
if (!mapKey || s.style === "offline") {
mapOptions = {
container: "map",
style: {
"version": 8,
"sources": {
"world": {
"type": "geojson",
"data": `${this.$config.staticUri}/geo/world.json`,
"maxzoom": 6
}
},
"glyphs": `${this.$config.staticUri}/font/{fontstack}/{range}.pbf`,
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": "#aadafe"
}
},
{
id: "land",
type: "fill",
source: "world",
// "source-layer": "land",
paint: {
"fill-color": "#cbe5ca",
},
},
{
"id": "country-abbrev",
"type": "symbol",
"source": "world",
"maxzoom": 3,
"layout": {
"text-field": "{abbrev}",
"text-font": ["Open Sans Semibold"],
"text-transform": "uppercase",
"text-max-width": 20,
"text-size": {
"stops": [[3, 10], [4, 11], [5, 12], [6, 16]]
},
"text-letter-spacing": {
"stops": [[4, 0], [5, 1], [6, 2]]
},
"text-line-height": {
"stops": [[5, 1.2], [6, 2]]
}
},
"paint": {
"text-halo-color": "#fff",
"text-halo-width": 1
},
},
{
"id": "country-border",
"type": "line",
"source": "world",
"paint": {
"line-color": "#226688",
"line-opacity": 0.25,
"line-dasharray": [6, 2, 2, 2],
"line-width": 1.2
}
},
{
"id": "country-name",
"type": "symbol",
"minzoom": 3,
"source": "world",
"layout": {
"text-field": "{name}",
"text-font": ["Open Sans Semibold"],
"text-max-width": 20,
"text-size": {
"stops": [[3, 10], [4, 11], [5, 12], [6, 16]]
}
},
"paint": {
"text-halo-color": "#fff",
"text-halo-width": 1
},
},
],
},
attributionControl: true,
customAttribution: this.attribution,
zoom: 0,
};
this.url = '';
} else {
this.url = 'https://api.maptiler.com/maps/' + s.style + '/{z}/{x}/{y}.png?key=' + mapKey;
}
this.filter = filter;
this.options = mapOptions;
});
},
query: function () {
return this.$route.params.q ? this.$route.params.q : '';
},
openPhoto(uid) {
// Abort if uid is empty or results aren't loaded.
if (!uid || this.loading || !this.result || !this.result.features || this.result.features.length === 0) {
return;
}
// Get request parameters.
const options = {
params: {
near: uid,
count: 1000,
},
};
this.loading = true;
// Perform get request to find nearby photos.
return Api.get("geo/view", options).then((r) => {
if (r && r.data && r.data.length > 0) {
// Show photos.
this.$viewer.show(Thumb.wrap(r.data), 0);
} else {
// Don't open viewer if nothing was found.
this.$notify.warn(this.$gettext("No pictures found"));
}
}).finally(() => {
this.loading = false;
});
},
formChange() {
if (this.loading) return;
this.search();
},
clearQuery() {
this.filter.q = '';
this.search();
},
updateQuery() {
if (this.loading) return;
if (this.query() !== this.filter.q) {
if (this.filter.q) {
this.$router.replace({name: "place", params: {q: this.filter.q}});
} else {
this.$router.replace({name: "places"});
}
}
},
searchParams() {
const params = {
count: this.maxCount,
offset: 0,
};
Object.assign(params, this.filter);
if (this.staticFilter) {
Object.assign(params, this.staticFilter);
}
return params;
},
search() {
if (this.loading) return;
// Don't query the same data more than once
if (JSON.stringify(this.lastFilter) === JSON.stringify(this.filter)) return;
this.loading = true;
Object.assign(this.lastFilter, this.filter);
this.updateQuery();
// Compose query params.
const options = {
params: this.searchParams(),
};
// Fetch results from server.
return Api.get("geo", options).then((response) => {
if (!response.data.features || response.data.features.length === 0) {
this.loading = false;
this.$notify.warn(this.$gettext("No pictures found"));
return;
}
this.result = response.data;
this.map.getSource("photos").setData(this.result);
if (this.filter.q || !this.initialized) {
this.map.fitBounds(this.result.bbox, {
maxZoom: 17,
padding: 100,
duration: this.settings.animate,
essential: false,
animate: this.settings.animate > 0
});
}
this.initialized = true;
this.updateMarkers();
}).finally(() => {
this.loading = false;
});
},
renderMap() {
this.map = new maplibregl.Map(this.options);
this.map.setLanguage(this.$config.values.settings.ui.language.split("-")[0]);
const controlPos = this.$rtl ? 'top-left' : 'top-right';
this.map.addControl(new maplibregl.NavigationControl({showCompass: true}), controlPos);
this.map.addControl(new maplibregl.FullscreenControl({container: document.querySelector('body')}), controlPos);
this.map.addControl(new maplibregl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true
}), controlPos);
this.map.on("load", () => this.onMapLoad());
},
updateMarkers() {
if (this.loading) return;
let newMarkers = {};
let features = this.map.querySourceFeatures("photos");
for (let i = 0; i < features.length; i++) {
let coords = features[i].geometry.coordinates;
let props = features[i].properties;
if (props.cluster) continue;
let id = features[i].id;
let marker = this.markers[id];
let token = this.$config.previewToken();
if (!marker) {
let el = document.createElement('div');
el.className = 'marker';
el.title = props.Title;
el.style.backgroundImage = `url(${this.$config.contentUri}/t/${props.Hash}/${token}/tile_50)`;
el.style.width = '50px';
el.style.height = '50px';
el.addEventListener('click', () => this.openPhoto(props.UID));
marker = this.markers[id] = new maplibregl.Marker({
element: el
}).setLngLat(coords);
} else {
marker.setLngLat(coords);
}
newMarkers[id] = marker;
if (!this.markersOnScreen[id]) {
marker.addTo(this.map);
}
}
for (let id in this.markersOnScreen) {
if (!newMarkers[id]) {
this.markersOnScreen[id].remove();
}
}
this.markersOnScreen = newMarkers;
},
onMapLoad() {
this.map.addSource('photos', {
type: 'geojson',
data: null,
cluster: true,
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});
this.map.addLayer({
id: 'clusters',
type: 'circle',
source: 'photos',
filter: ['has', 'point_count'],
paint: {
'circle-color': [
'step',
['get', 'point_count'],
'#2DC4B2',
100,
'#3BB3C3',
750,
'#669EC4'
],
'circle-radius': [
'step',
['get', 'point_count'],
20,
100,
30,
750,
40
]
}
});
this.map.addLayer({
id: 'cluster-count',
type: 'symbol',
source: 'photos',
filter: ['has', 'point_count'],
layout: {
'text-field': '{point_count_abbreviated}',
'text-font': this.mapFont,
'text-size': 13
}
});
this.map.on('render', this.updateMarkers);
this.map.on('click', 'clusters', (e) => {
const features = this.map.queryRenderedFeatures(e.point, {
layers: ['clusters']
});
const clusterId = features[0].properties.cluster_id;
this.map.getSource('photos').getClusterExpansionZoom(
clusterId,
(err, zoom) => {
if (err) return;
this.map.easeTo({
center: features[0].geometry.coordinates,
zoom: zoom
});
}
);
});
this.map.on('mouseenter', 'clusters', () => {
this.map.getCanvas().style.cursor = 'pointer';
});
this.map.on('mouseleave', 'clusters', () => {
this.map.getCanvas().style.cursor = '';
});
this.search();
},
},
};
</script>

View File

@@ -1,5 +1,6 @@
import Albums from "share/albums.vue"; import Albums from "share/albums.vue";
import AlbumPhotos from "share/photos.vue"; import AlbumPhotos from "share/photos.vue";
import Places from "pages/places.vue";
const c = window.__CONFIG__; const c = window.__CONFIG__;
const siteTitle = c.siteAuthor ? c.siteAuthor : c.name; const siteTitle = c.siteAuthor ? c.siteAuthor : c.name;
@@ -24,6 +25,12 @@ export default [
component: AlbumPhotos, component: AlbumPhotos,
meta: { title: shareTitle, auth: true, hideNav: true }, meta: { title: shareTitle, auth: true, hideNav: true },
}, },
{
name: "album_place",
path: "/places/:album/:q",
component: Places,
meta: { title: shareTitle, auth: true, hideNav: true },
},
{ {
path: "*", path: "*",
redirect: { name: "albums" }, redirect: { name: "albums" },

View File

@@ -2,7 +2,7 @@ package acl
// Predefined grants to simplify configuration. // Predefined grants to simplify configuration.
var ( var (
GrantFullAccess = Grant{FullAccess: true, AccessAll: true, ActionCreate: true, ActionUpdate: true, ActionDelete: true, ActionDownload: true, ActionShare: true, ActionRate: true, ActionReact: true, ActionManage: true, ActionSubscribe: true} GrantFullAccess = Grant{FullAccess: true, AccessAll: true, AccessLibrary: true, ActionCreate: true, ActionUpdate: true, ActionDelete: true, ActionDownload: true, ActionShare: true, ActionRate: true, ActionReact: true, ActionManage: true, ActionSubscribe: true}
GrantSubscribeAll = Grant{AccessAll: true, ActionSubscribe: true} GrantSubscribeAll = Grant{AccessAll: true, ActionSubscribe: true}
GrantSubscribeOwn = Grant{AccessOwn: true, ActionSubscribe: true} GrantSubscribeOwn = Grant{AccessOwn: true, ActionSubscribe: true}
) )

View File

@@ -20,7 +20,7 @@ func TestMain(m *testing.M) {
log.SetLevel(logrus.TraceLevel) log.SetLevel(logrus.TraceLevel)
event.AuditLog = log event.AuditLog = log
c := config.NewTestConfig("api") c := config.TestConfig()
service.SetConfig(c) service.SetConfig(c)
code := m.Run() code := m.Run()

View File

@@ -13,22 +13,28 @@ func Auth(c *gin.Context, resource acl.Resource, grant acl.Permission) *entity.S
} }
// AuthAny checks if at least one permission allows access and returns the session in this case. // AuthAny checks if at least one permission allows access and returns the session in this case.
func AuthAny(c *gin.Context, resource acl.Resource, grants acl.Permissions) *entity.Session { func AuthAny(c *gin.Context, resource acl.Resource, grants acl.Permissions) (s *entity.Session) {
// Get session ID, if any. // Get client IP address and session ID, if any.
ip := ClientIP(c)
sessId := SessionID(c) sessId := SessionID(c)
// Find and return the client session after all checks have passed. // Find client session.
if s := Session(sessId); s == nil { if s = Session(sessId); s == nil {
event.AuditWarn([]string{ClientIP(c), "unauthenticated", "%s %s as unknown user", "denied"}, grants.String(), string(resource)) event.AuditWarn([]string{ip, "unauthenticated", "%s %s as unknown user", "denied"}, grants.String(), string(resource))
return entity.SessionStatusUnauthorized() return entity.SessionStatusUnauthorized()
} else if s.User() == nil { } else {
event.AuditWarn([]string{ClientIP(c), "session %s", "%s %s as unknown user", "denied"}, s.RefID, grants.String(), string(resource)) s.SetClientIP(ip)
}
// Check authorization.
if s.User() == nil {
event.AuditWarn([]string{ip, "session %s", "%s %s as unknown user", "denied"}, s.RefID, grants.String(), string(resource))
return entity.SessionStatusUnauthorized() return entity.SessionStatusUnauthorized()
} else if acl.Resources.DenyAll(resource, s.User().AclRole(), grants) { } else if acl.Resources.DenyAll(resource, s.User().AclRole(), grants) {
event.AuditErr([]string{ClientIP(c), "session %s", "%s %s as %s", "denied"}, s.RefID, grants.String(), string(resource), s.User().AclRole().String()) event.AuditErr([]string{ip, "session %s", "%s %s as %s", "denied"}, s.RefID, grants.String(), string(resource), s.User().AclRole().String())
return entity.SessionStatusForbidden() return entity.SessionStatusForbidden()
} else { } else {
event.AuditInfo([]string{ClientIP(c), "session %s", "%s %s as %s", "granted"}, s.RefID, grants.String(), string(resource), s.User().AclRole().String()) event.AuditInfo([]string{ip, "session %s", "%s %s as %s", "granted"}, s.RefID, grants.String(), string(resource), s.User().AclRole().String())
return s return s
} }
} }

View File

@@ -3,12 +3,10 @@ package api
import ( import (
"net/http" "net/http"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/service"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
) )
@@ -50,7 +48,7 @@ func GetSession(router *gin.RouterGroup) {
var clientConfig config.ClientConfig var clientConfig config.ClientConfig
if conf := service.Config(); conf == nil { if conf := service.Config(); conf == nil {
log.Errorf("session: config is nil - possible bug") log.Errorf("session: config is not set - possible bug")
AbortUnexpected(c) AbortUnexpected(c)
return return
} else if sess.User().IsVisitor() { } else if sess.User().IsVisitor() {

View File

@@ -18,24 +18,13 @@ const (
) )
func PublishPhotoEvent(e EntityEvent, uid string, c *gin.Context) { func PublishPhotoEvent(e EntityEvent, uid string, c *gin.Context) {
f := form.SearchPhotos{UID: uid, Merged: true} if result, _, err := search.Photos(form.SearchPhotos{UID: uid, Merged: true}); err != nil {
log.Warnf("search: %s", err)
if err := f.ParseQueryString(); err != nil {
log.Errorf("publish: %s", err)
AbortBadRequest(c)
return
}
result, _, err := search.Photos(f)
if err != nil {
log.Error(err)
AbortUnexpected(c) AbortUnexpected(c)
return } else {
}
event.PublishEntities("photos", string(e), result) event.PublishEntities("photos", string(e), result)
} }
}
func PublishAlbumEvent(e EntityEvent, uid string, c *gin.Context) { func PublishAlbumEvent(e EntityEvent, uid string, c *gin.Context) {
f := form.SearchAlbums{UID: uid} f := form.SearchAlbums{UID: uid}

View File

@@ -3,10 +3,12 @@ package api
import ( import (
"net/http" "net/http"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
"github.com/dustin/go-humanize/english"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/photoprism/photoprism/internal/acl" "github.com/photoprism/photoprism/internal/acl"
@@ -21,12 +23,16 @@ import (
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
) )
const (
UploadPath = "/upload"
)
// StartImport imports media files from a directory and converts/indexes them as needed. // StartImport imports media files from a directory and converts/indexes them as needed.
// //
// POST /api/v1/import* // POST /api/v1/import*
func StartImport(router *gin.RouterGroup) { func StartImport(router *gin.RouterGroup) {
router.POST("/import/*path", func(c *gin.Context) { router.POST("/import/*path", func(c *gin.Context) {
s := Auth(c, acl.ResourceFiles, acl.ActionManage) s := AuthAny(c, acl.ResourceFiles, acl.Permissions{acl.ActionManage, acl.ActionUpload})
if s.Abort(c) { if s.Abort(c) {
return return
@@ -48,66 +54,93 @@ func StartImport(router *gin.RouterGroup) {
return return
} }
subPath := "" srcFolder := ""
path := conf.ImportPath() importPath := conf.ImportPath()
if subPath = clean.Path(c.Param("path")); subPath != "" && subPath != "/" { // Import from sub-folder?
subPath = strings.Replace(subPath, ".", "", -1) if srcFolder = clean.Path(c.Param("path")); srcFolder != "" && srcFolder != "/" {
path = filepath.Join(path, subPath) srcFolder = strings.Replace(srcFolder, ".", "", -1)
} else if f.Path != "" { } else if f.Path != "" {
subPath = strings.Replace(f.Path, ".", "", -1) srcFolder = strings.Replace(f.Path, ".", "", -1)
path = filepath.Join(path, subPath)
} }
path = filepath.Clean(path) // To avoid conflicts, uploads are imported from "import_path/upload/session_ref/timestamp".
if token := path.Base(srcFolder); token != "" && path.Dir(srcFolder) == UploadPath {
srcFolder = path.Join(UploadPath, s.RefID+token)
event.AuditInfo([]string{ClientIP(c), "session %s", "import uploads from %s as %s", "granted"}, s.RefID, clean.Log(srcFolder), s.User().AclRole().String())
} else if acl.Resources.Deny(acl.ResourceFiles, s.User().AclRole(), acl.ActionManage) {
event.AuditErr([]string{ClientIP(c), "session %s", "import files from %s as %s", "denied"}, s.RefID, clean.Log(srcFolder), s.User().AclRole().String())
AbortForbidden(c)
return
}
importPath = path.Join(importPath, srcFolder)
imp := service.Import() imp := service.Import()
RemoveFromFolderCache(entity.RootImport) RemoveFromFolderCache(entity.RootImport)
var opt photoprism.ImportOptions var destFolder string
if destFolder = s.User().UploadPath; destFolder == "" {
if f.Move { destFolder = conf.ImportDest()
event.InfoMsg(i18n.MsgMovingFilesFrom, clean.Log(filepath.Base(path)))
opt = photoprism.ImportOptionsMove(path)
} else {
event.InfoMsg(i18n.MsgCopyingFilesFrom, clean.Log(filepath.Base(path)))
opt = photoprism.ImportOptionsCopy(path)
} }
if len(f.Albums) > 0 { var opt photoprism.ImportOptions
// Copy or move files to the destination folder?
if f.Move {
event.InfoMsg(i18n.MsgMovingFilesFrom, clean.Log(filepath.Base(importPath)))
opt = photoprism.ImportOptionsMove(importPath, destFolder)
} else {
event.InfoMsg(i18n.MsgCopyingFilesFrom, clean.Log(filepath.Base(importPath)))
opt = photoprism.ImportOptionsCopy(importPath, destFolder)
}
// Add imported files to albums if allowed.
if len(f.Albums) > 0 &&
acl.Resources.AllowAny(acl.ResourceAlbums, s.User().AclRole(), acl.Permissions{acl.ActionCreate, acl.ActionUpload}) {
log.Debugf("import: adding files to album %s", clean.Log(strings.Join(f.Albums, " and "))) log.Debugf("import: adding files to album %s", clean.Log(strings.Join(f.Albums, " and ")))
opt.Albums = f.Albums opt.Albums = f.Albums
} }
imp.Start(opt) // Start import.
imported := imp.Start(opt)
if subPath != "" && path != conf.ImportPath() && fs.DirIsEmpty(path) { // Delete empty import directory.
if err := os.Remove(path); err != nil { if srcFolder != "" && importPath != conf.ImportPath() && fs.DirIsEmpty(importPath) {
log.Errorf("import: failed deleting empty folder %s: %s", clean.Log(path), err) if err := os.Remove(importPath); err != nil {
log.Errorf("import: failed deleting empty folder %s: %s", clean.Log(importPath), err)
} else { } else {
log.Infof("import: deleted empty folder %s", clean.Log(path)) log.Infof("import: deleted empty folder %s", clean.Log(importPath))
} }
} }
moments := service.Moments() // Update moments if files have been imported.
if n := len(imported); n == 0 {
if err := moments.Start(); err != nil { log.Infof("import: no new files found to import", clean.Log(importPath))
} else {
log.Infof("import: imported %s", english.Plural(n, "file", "files"))
if moments := service.Moments(); moments == nil {
log.Warnf("import: moments service not set - possible bug")
} else if err := moments.Start(); err != nil {
log.Warnf("moments: %s", err) log.Warnf("moments: %s", err)
} }
}
elapsed := int(time.Since(start).Seconds()) elapsed := int(time.Since(start).Seconds())
// Show success message.
msg := i18n.Msg(i18n.MsgImportCompletedIn, elapsed) msg := i18n.Msg(i18n.MsgImportCompletedIn, elapsed)
event.Success(msg) event.Success(msg)
event.Publish("import.completed", event.Data{"path": path, "seconds": elapsed}) event.Publish("import.completed", event.Data{"path": importPath, "seconds": elapsed})
event.Publish("index.completed", event.Data{"path": path, "seconds": elapsed}) event.Publish("index.completed", event.Data{"path": importPath, "seconds": elapsed})
for _, uid := range f.Albums { for _, uid := range f.Albums {
PublishAlbumEvent(EntityUpdated, uid, c) PublishAlbumEvent(EntityUpdated, uid, c)
} }
// Update the user interface.
UpdateClientConfig() UpdateClientConfig()
// Update album, label, and subject cover thumbs. // Update album, label, and subject cover thumbs.

View File

@@ -16,10 +16,9 @@ import (
) )
// SearchPhotos searches the pictures index and returns the result as JSON. // SearchPhotos searches the pictures index and returns the result as JSON.
// See form.SearchPhotos for supported search params and data types.
// //
// GET /api/v1/photos // GET /api/v1/photos
//
// See form.SearchPhotos for supported search params and data types.
func SearchPhotos(router *gin.RouterGroup) { func SearchPhotos(router *gin.RouterGroup) {
// searchPhotos checking authorization and parses the search request. // searchPhotos checking authorization and parses the search request.
searchForm := func(c *gin.Context) (f form.SearchPhotos, s *entity.Session, err error) { searchForm := func(c *gin.Context) (f form.SearchPhotos, s *entity.Session, err error) {
@@ -32,59 +31,13 @@ func SearchPhotos(router *gin.RouterGroup) {
// Abort if request params are invalid. // Abort if request params are invalid.
if err = c.MustBindWith(&f, binding.Form); err != nil { if err = c.MustBindWith(&f, binding.Form); err != nil {
event.AuditWarn([]string{ClientIP(c), "session %s", "photos", "form invalid", "%s"}, s.RefID, err) event.AuditWarn([]string{ClientIP(c), "session %s", string(acl.ResourcePhotos), "form invalid", "%s"}, s.RefID, err)
AbortBadRequest(c) AbortBadRequest(c)
return f, s, err return f, s, err
} }
// Limit results to a specific album? // Ignore private flag if feature is disabled.
if f.Album == "" { if !service.Config().Settings().Features.Private {
if acl.Resources.Deny(acl.ResourcePhotos, s.User().AclRole(), acl.ActionSearch) {
event.AuditErr([]string{ClientIP(c), "session %s", "%s %s as %s", "denied"}, s.RefID, acl.ActionSearch.String(), string(acl.ResourcePhotos), s.User().AclRole().String())
c.AbortWithStatusJSON(http.StatusForbidden, i18n.NewResponse(http.StatusForbidden, i18n.ErrForbidden))
return f, s, i18n.Error(i18n.ErrForbidden)
}
} else if a, err := entity.CachedAlbumByUID(f.Album); err != nil {
event.AuditWarn([]string{ClientIP(c), "session %s", "photos", "album", f.Album, "not found"}, s.RefID)
AbortAlbumNotFound(c)
return f, s, i18n.Error(i18n.ErrAlbumNotFound)
} else {
f.Filter = a.AlbumFilter
}
// Parse query string and filter.
if err = f.ParseQueryString(); err != nil {
log.Debugf("search: %s", err)
AbortBadRequest(c)
return f, s, err
}
conf := service.Config()
// Enforce ACL.
if acl.Resources.Deny(acl.ResourcePhotos, s.User().AclRole(), acl.AccessPrivate) {
f.Public = true
f.Private = false
}
if acl.Resources.Deny(acl.ResourcePhotos, s.User().AclRole(), acl.ActionDelete) {
f.Archived = false
f.Review = false
}
if acl.Resources.Deny(acl.ResourceFiles, s.User().AclRole(), acl.ActionManage) {
f.Hidden = false
}
// Sharing link visitors may only see public content in shared albums.
if s.IsVisitor() {
if f.Album == "" || !s.HasShare(f.Album) {
event.AuditErr([]string{ClientIP(c), "session %s", "photos", "shared album", f.Album, "not shared"}, s.RefID)
AbortForbidden(c)
return f, s, i18n.Error(i18n.ErrUnauthorized)
}
f.UID = ""
f.Albums = ""
} else if !conf.Settings().Features.Private {
f.Public = false f.Public = false
} }
@@ -100,10 +53,10 @@ func SearchPhotos(router *gin.RouterGroup) {
return return
} }
result, count, err := search.Photos(f) result, count, err := search.UserPhotos(f, s)
if err != nil { if err != nil {
event.AuditWarn([]string{ClientIP(c), "session %s", "photos", "search", "%s"}, s.RefID, err) event.AuditWarn([]string{ClientIP(c), "session %s", string(acl.ResourcePhotos), "search", "%s"}, s.RefID, err)
AbortBadRequest(c) AbortBadRequest(c)
return return
} }
@@ -129,10 +82,10 @@ func SearchPhotos(router *gin.RouterGroup) {
conf := service.Config() conf := service.Config()
result, count, err := search.PhotosViewerResults(f, conf.ContentUri(), conf.ApiUri(), conf.PreviewToken(), conf.DownloadToken()) result, count, err := search.UserPhotosViewerResults(f, s, conf.ContentUri(), conf.ApiUri(), conf.PreviewToken(), conf.DownloadToken())
if err != nil { if err != nil {
event.AuditWarn([]string{ClientIP(c), "session %s", "photos", "view", "%s"}, s.RefID, err) event.AuditWarn([]string{ClientIP(c), "session %s", string(acl.ResourcePhotos), "view", "%s"}, s.RefID, err)
AbortBadRequest(c) AbortBadRequest(c)
return return
} }

View File

@@ -7,7 +7,7 @@ import (
"github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/binding"
"github.com/photoprism/photoprism/internal/acl" "github.com/photoprism/photoprism/internal/acl"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/internal/search" "github.com/photoprism/photoprism/internal/search"
"github.com/photoprism/photoprism/internal/service" "github.com/photoprism/photoprism/internal/service"
@@ -16,71 +16,48 @@ import (
) )
// SearchGeo finds photos and returns results as JSON, so they can be displayed on a map or in a viewer. // SearchGeo finds photos and returns results as JSON, so they can be displayed on a map or in a viewer.
// See form.SearchPhotosGeo for supported search params and data types.
// //
// GET /api/v1/geo // GET /api/v1/geo
//
// See form.SearchPhotosGeo for supported search params and data types.
func SearchGeo(router *gin.RouterGroup) { func SearchGeo(router *gin.RouterGroup) {
handler := func(c *gin.Context) { handler := func(c *gin.Context) {
s := Auth(c, acl.ResourcePhotos, acl.ActionSearch) s := AuthAny(c, acl.ResourcePlaces, acl.Permissions{acl.ActionSearch, acl.ActionView, acl.AccessShared})
// Abort if permission was not granted.
if s.Abort(c) { if s.Abort(c) {
return return
} }
var f form.SearchPhotosGeo var f form.SearchPhotosGeo
var err error
err := c.MustBindWith(&f, binding.Form) // Abort if request params are invalid.
if err = c.MustBindWith(&f, binding.Form); err != nil {
if err != nil { event.AuditWarn([]string{ClientIP(c), "session %s", string(acl.ResourcePlaces), "form invalid", "%s"}, s.RefID, err)
AbortBadRequest(c)
return
}
// Limit results to a specific album?
if f.Album == "" {
// Do nothing.
} else if a, err := entity.CachedAlbumByUID(f.Album); err != nil {
AbortAlbumNotFound(c)
return
} else {
f.Filter = a.AlbumFilter
}
// Parse query string and filter.
if err = f.ParseQueryString(); err != nil {
log.Debugf("search: %s", err)
AbortBadRequest(c) AbortBadRequest(c)
return return
} }
conf := service.Config() conf := service.Config()
// Sharing link visitors may only see public content. // Ignore private flag if feature is disabled.
if s.IsVisitor() { if !conf.Settings().Features.Private {
if f.Album == "" || !s.HasShare(f.Album) { f.Public = false
AbortForbidden(c)
return
}
f.Public = true
f.Private = false
f.Archived = false
f.Review = false
} else {
f.Public = conf.Settings().Features.Private
} }
// Find matching pictures. // Find matching pictures.
photos, err := search.PhotosGeo(f) photos, err := search.UserPhotosGeo(f, s)
if err != nil { if err != nil {
log.Warnf("search: %s", err) event.AuditWarn([]string{ClientIP(c), "session %s", string(acl.ResourcePlaces), "search", "%s"}, s.RefID, err)
AbortBadRequest(c) AbortBadRequest(c)
return return
} }
// Add response headers. // Add response headers.
AddCountHeader(c, len(photos))
AddLimitHeader(c, f.Count)
AddOffsetHeader(c, f.Offset)
AddTokenHeaders(c) AddTokenHeaders(c)
var resp []byte var resp []byte
@@ -88,7 +65,6 @@ func SearchGeo(router *gin.RouterGroup) {
// Render JSON response. // Render JSON response.
switch clean.Token(c.Param("format")) { switch clean.Token(c.Param("format")) {
case "view": case "view":
conf := service.Config()
resp, err = photos.ViewerJSON(conf.ContentUri(), conf.ApiUri(), conf.PreviewToken(), conf.DownloadToken()) resp, err = photos.ViewerJSON(conf.ContentUri(), conf.ApiUri(), conf.PreviewToken(), conf.DownloadToken())
default: default:
resp, err = photos.GeoJSON() resp, err = photos.GeoJSON()

View File

@@ -15,23 +15,26 @@ import (
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
) )
// Upload adds files to the import folder, from where supported file types are moved to the originals folders.
//
// POST /api/v1/upload/:path // POST /api/v1/upload/:path
func Upload(router *gin.RouterGroup) { func Upload(router *gin.RouterGroup) {
router.POST("/upload/:path", func(c *gin.Context) { router.POST("/upload/:token", func(c *gin.Context) {
conf := service.Config() conf := service.Config()
if conf.ReadOnly() || !conf.Settings().Features.Upload { if conf.ReadOnly() || !conf.Settings().Features.Upload {
Abort(c, http.StatusForbidden, i18n.ErrReadOnly) Abort(c, http.StatusForbidden, i18n.ErrReadOnly)
return return
} }
s := Auth(c, acl.ResourcePhotos, acl.ActionUpload) s := AuthAny(c, acl.ResourceFiles, acl.Permissions{acl.ActionManage, acl.ActionUpload})
if s.Abort(c) { if s.Abort(c) {
return return
} }
start := time.Now() start := time.Now()
subPath := clean.Path(c.Param("path")) token := clean.Token(c.Param("token"))
f, err := c.MultipartForm() f, err := c.MultipartForm()
@@ -45,18 +48,19 @@ func Upload(router *gin.RouterGroup) {
files := f.File["files"] files := f.File["files"]
uploaded := len(files) uploaded := len(files)
var uploads []string var uploads []string
p := path.Join(conf.ImportPath(), "upload", subPath) uploadDir := path.Join(conf.ImportPath(), "upload", s.RefID+token)
if err := os.MkdirAll(p, os.ModePerm); err != nil { if err = os.MkdirAll(uploadDir, os.ModePerm); err != nil {
log.Errorf("upload: failed creating folder %s", clean.Log(subPath)) log.Errorf("upload: failed creating folder %s", clean.Log(filepath.Base(uploadDir)))
AbortBadRequest(c) AbortBadRequest(c)
return return
} }
for _, file := range files { for _, file := range files {
filename := path.Join(p, filepath.Base(file.Filename)) filename := path.Join(uploadDir, filepath.Base(file.Filename))
log.Debugf("upload: saving file %s", clean.Log(file.Filename)) log.Debugf("upload: saving file %s", clean.Log(file.Filename))

View File

@@ -71,9 +71,9 @@ func Import() error {
var opt photoprism.ImportOptions var opt photoprism.ImportOptions
if conf.Settings().Import.Move { if conf.Settings().Import.Move {
opt = photoprism.ImportOptionsMove(path) opt = photoprism.ImportOptionsMove(path, conf.ImportDest())
} else { } else {
opt = photoprism.ImportOptionsCopy(path) opt = photoprism.ImportOptionsCopy(path, conf.ImportDest())
} }
imported := imp.Start(opt) imported := imp.Start(opt)

View File

@@ -1,5 +1,5 @@
/* /*
Package commands provides photoprism CLI (sub-)commands. Package commands provides the CLI commands of PhotoPrism.
Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved. Copyright (c) 2018 - 2022 PhotoPrism UG. All rights reserved.
@@ -29,13 +29,12 @@ import (
"os" "os"
"syscall" "syscall"
"github.com/photoprism/photoprism/internal/service"
"github.com/sevlyar/go-daemon" "github.com/sevlyar/go-daemon"
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/internal/service"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
) )

View File

@@ -17,7 +17,7 @@ import (
var ConvertCommand = cli.Command{ var ConvertCommand = cli.Command{
Name: "convert", Name: "convert",
Usage: "Converts files in other formats to JPEG and AVC as needed", Usage: "Converts files in other formats to JPEG and AVC as needed",
ArgsUsage: "[originals folder]", ArgsUsage: "[SUB-FOLDER]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ cli.BoolFlag{
Name: "force, f", Name: "force, f",

View File

@@ -12,6 +12,7 @@ import (
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/photoprism" "github.com/photoprism/photoprism/internal/photoprism"
"github.com/photoprism/photoprism/internal/service" "github.com/photoprism/photoprism/internal/service"
"github.com/photoprism/photoprism/pkg/clean"
) )
// CopyCommand registers the copy cli command. // CopyCommand registers the copy cli command.
@@ -19,7 +20,13 @@ var CopyCommand = cli.Command{
Name: "cp", Name: "cp",
Aliases: []string{"copy"}, Aliases: []string{"copy"},
Usage: "Copies media files to originals", Usage: "Copies media files to originals",
ArgsUsage: "[path]", ArgsUsage: "[IMPORT PATH]",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "dest, d",
Usage: "relative originals `PATH` to which the files should be imported",
},
},
Action: copyAction, Action: copyAction,
} }
@@ -64,10 +71,17 @@ func copyAction(ctx *cli.Context) error {
return errors.New("import path is identical with originals") return errors.New("import path is identical with originals")
} }
log.Infof("copying media files from %s to %s", sourcePath, conf.OriginalsPath()) var destFolder string
if ctx.IsSet("dest") {
destFolder = clean.UserPath(ctx.String("dest"))
} else {
destFolder = conf.ImportDest()
}
log.Infof("copying media files from %s to %s", sourcePath, filepath.Join(conf.OriginalsPath(), destFolder))
w := service.Import() w := service.Import()
opt := photoprism.ImportOptionsCopy(sourcePath) opt := photoprism.ImportOptionsCopy(sourcePath, destFolder)
w.Start(opt) w.Start(opt)

View File

@@ -53,7 +53,7 @@ var FacesCommand = cli.Command{
{ {
Name: "index", Name: "index",
Usage: "Searches originals for faces", Usage: "Searches originals for faces",
ArgsUsage: "[originals folder]", ArgsUsage: "[SUB-FOLDER]",
Action: facesIndexAction, Action: facesIndexAction,
}, },
{ {

View File

@@ -12,6 +12,7 @@ import (
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/photoprism" "github.com/photoprism/photoprism/internal/photoprism"
"github.com/photoprism/photoprism/internal/service" "github.com/photoprism/photoprism/internal/service"
"github.com/photoprism/photoprism/pkg/clean"
) )
// ImportCommand registers the import cli command. // ImportCommand registers the import cli command.
@@ -19,7 +20,13 @@ var ImportCommand = cli.Command{
Name: "mv", Name: "mv",
Aliases: []string{"import"}, Aliases: []string{"import"},
Usage: "Moves media files to originals", Usage: "Moves media files to originals",
ArgsUsage: "[path]", ArgsUsage: "[SOURCE PATH]",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "dest, d",
Usage: "relative originals `PATH` to which the files should be imported",
},
},
Action: importAction, Action: importAction,
} }
@@ -64,10 +71,17 @@ func importAction(ctx *cli.Context) error {
return errors.New("import path is identical with originals") return errors.New("import path is identical with originals")
} }
log.Infof("moving media files from %s to %s", sourcePath, conf.OriginalsPath()) var destFolder string
if ctx.IsSet("dest") {
destFolder = clean.UserPath(ctx.String("dest"))
} else {
destFolder = conf.ImportDest()
}
log.Infof("moving media files from %s to %s", sourcePath, filepath.Join(conf.OriginalsPath(), destFolder))
w := service.Import() w := service.Import()
opt := photoprism.ImportOptionsMove(sourcePath) opt := photoprism.ImportOptionsMove(sourcePath, destFolder)
w.Start(opt) w.Start(opt)

View File

@@ -20,7 +20,7 @@ import (
var IndexCommand = cli.Command{ var IndexCommand = cli.Command{
Name: "index", Name: "index",
Usage: "Indexes original media files", Usage: "Indexes original media files",
ArgsUsage: "[originals folder]", ArgsUsage: "[SUB-FOLDER]",
Flags: indexFlags, Flags: indexFlags,
Action: indexAction, Action: indexAction,
} }

View File

@@ -18,7 +18,7 @@ var MigrationsStatusCommand = cli.Command{
Name: "ls", Name: "ls",
Aliases: []string{"status", "show"}, Aliases: []string{"status", "show"},
Usage: "Lists the status of schema migrations", Usage: "Lists the status of schema migrations",
ArgsUsage: "[migrations...]", ArgsUsage: "[MIGRATIONS...]",
Flags: report.CliFlags, Flags: report.CliFlags,
Action: migrationsStatusAction, Action: migrationsStatusAction,
} }
@@ -27,7 +27,7 @@ var MigrationsRunCommand = cli.Command{
Name: "run", Name: "run",
Aliases: []string{"execute", "migrate"}, Aliases: []string{"execute", "migrate"},
Usage: "Executes database schema migrations", Usage: "Executes database schema migrations",
ArgsUsage: "[migrations...]", ArgsUsage: "[MIGRATIONS...]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ cli.BoolFlag{
Name: "failed, f", Name: "failed, f",

View File

@@ -10,12 +10,11 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/photoprism/photoprism/internal/service"
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/service"
"github.com/photoprism/photoprism/pkg/clean" "github.com/photoprism/photoprism/pkg/clean"
) )

View File

@@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/dustin/go-humanize/english" "github.com/dustin/go-humanize/english"
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/config"

View File

@@ -31,7 +31,7 @@ var RestoreCommand = cli.Command{
Name: "restore", Name: "restore",
Description: restoreDescription, Description: restoreDescription,
Usage: "Restores the index from an SQL dump and optionally albums from YAML files", Usage: "Restores the index from an SQL dump and optionally albums from YAML files",
ArgsUsage: "[filename.sql]", ArgsUsage: "filename.sql",
Flags: restoreFlags, Flags: restoreFlags,
Action: restoreAction, Action: restoreAction,
} }

View File

@@ -26,6 +26,7 @@ func TestShowConfigCommand(t *testing.T) {
assert.Contains(t, output, "config-path") assert.Contains(t, output, "config-path")
assert.Contains(t, output, "originals-path") assert.Contains(t, output, "originals-path")
assert.Contains(t, output, "import-path") assert.Contains(t, output, "import-path")
assert.Contains(t, output, "import-dest")
assert.Contains(t, output, "cache-path") assert.Contains(t, output, "cache-path")
assert.Contains(t, output, "assets-path") assert.Contains(t, output, "assets-path")
assert.Contains(t, output, "darktable-cli") assert.Contains(t, output, "darktable-cli")

View File

@@ -8,13 +8,13 @@ import (
// Usage hints for the user management subcommands. // Usage hints for the user management subcommands.
const ( const (
UserDisplayNameUsage = "full `NAME` for display in the interface" UserNameUsage = "full `NAME` for display in the interface"
UserEmailUsage = "unique `EMAIL` address of the user" UserEmailUsage = "unique `EMAIL` address of the user"
UserPasswordUsage = "`PASSWORD` for authentication" UserPasswordUsage = "`PASSWORD` for authentication"
UserRoleUsage = "user account `ROLE`" UserRoleUsage = "user account `ROLE`"
UserAttrUsage = "custom user account `ATTRIBUTES`" UserAttrUsage = "custom user account `ATTRIBUTES`"
UserAdminUsage = "make user super admin with full access" UserAdminUsage = "make user super admin with full access"
UserDisableLoginUsage = "disable login and use of the web interface" UserNoLoginUsage = "disable login on the web interface"
UserCanSyncUsage = "allow to sync files via WebDAV" UserCanSyncUsage = "allow to sync files via WebDAV"
) )
@@ -34,8 +34,8 @@ var UsersCommand = cli.Command{
// UserFlags specifies the add and modify user command flags. // UserFlags specifies the add and modify user command flags.
var UserFlags = []cli.Flag{ var UserFlags = []cli.Flag{
cli.StringFlag{ cli.StringFlag{
Name: "displayname, n", Name: "name, n",
Usage: UserDisplayNameUsage, Usage: UserNameUsage,
}, },
cli.StringFlag{ cli.StringFlag{
Name: "email, m", Name: "email, m",
@@ -59,8 +59,8 @@ var UserFlags = []cli.Flag{
Usage: UserAdminUsage, Usage: UserAdminUsage,
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "disable-login, d", Name: "no-login, l",
Usage: UserDisableLoginUsage, Usage: UserNoLoginUsage,
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "can-sync, w", Name: "can-sync, w",

View File

@@ -82,6 +82,17 @@ type ClientConfig struct {
Ext Values `json:"ext"` Ext Values `json:"ext"`
} }
// ApplyACL updates the client config values based on the ACL and Role provided.
func (c ClientConfig) ApplyACL(a acl.ACL, r acl.Role) ClientConfig {
if c.Settings != nil {
c.Settings = c.Settings.ApplyACL(a, r)
}
c.ACL = a.Grants(r)
return c
}
// Years represents a list of years. // Years represents a list of years.
type Years []int type Years []int
@@ -189,7 +200,7 @@ func (c *Config) Flags() (flags []string) {
// ClientPublic returns config values for use by the JavaScript UI and other clients. // ClientPublic returns config values for use by the JavaScript UI and other clients.
func (c *Config) ClientPublic() ClientConfig { func (c *Config) ClientPublic() ClientConfig {
if c.Public() { if c.Public() {
return c.ClientUser(true) return c.ClientUser(true).ApplyACL(acl.Resources, acl.RoleAdmin)
} }
a := c.ClientAssets() a := c.ClientAssets()
@@ -548,18 +559,13 @@ func (c *Config) ClientUser(withSettings bool) ClientConfig {
// ClientRole provides the client config values for the specified user role. // ClientRole provides the client config values for the specified user role.
func (c *Config) ClientRole(role acl.Role) ClientConfig { func (c *Config) ClientRole(role acl.Role) ClientConfig {
result := c.ClientUser(true) return c.ClientUser(true).ApplyACL(acl.Resources, role)
result.Settings = result.Settings.ApplyACL(acl.Resources, role)
result.ACL = acl.Resources.Grants(role)
return result
} }
// ClientSession provides the client config values for the specified session. // ClientSession provides the client config values for the specified session.
func (c *Config) ClientSession(sess *entity.Session) ClientConfig { func (c *Config) ClientSession(sess *entity.Session) ClientConfig {
result := c.ClientUser(false) result := c.ClientUser(false).ApplyACL(acl.Resources, sess.User().AclRole())
result.Settings = c.SessionSettings(sess) result.Settings = c.SessionSettings(sess)
result.ACL = acl.Resources.Grants(sess.User().AclRole())
return result return result
} }

View File

@@ -148,7 +148,7 @@ func TestConfig_ClientRoleConfig(t *testing.T) {
Logs: false, Logs: false,
Moments: false, Moments: false,
People: false, People: false,
Places: false, Places: true,
Private: false, Private: false,
Ratings: false, Ratings: false,
Reactions: false, Reactions: false,

View File

@@ -256,6 +256,11 @@ func (c *Config) ImportPath() string {
return fs.Abs(c.options.ImportPath) return fs.Abs(c.options.ImportPath)
} }
// ImportDest returns the relative originals path to which the files should be imported by default.
func (c *Config) ImportDest() string {
return clean.UserPath(c.options.ImportDest)
}
// SidecarPath returns the storage path for generated sidecar files (relative or absolute). // SidecarPath returns the storage path for generated sidecar files (relative or absolute).
func (c *Config) SidecarPath() string { func (c *Config) SidecarPath() string {
if c.options.SidecarPath == "" { if c.options.SidecarPath == "" {

View File

@@ -51,6 +51,7 @@ func (c *Config) Report() (rows [][]string, cols []string) {
{"cmd-cache-path", c.CmdCachePath()}, {"cmd-cache-path", c.CmdCachePath()},
{"thumb-cache-path", c.ThumbCachePath()}, {"thumb-cache-path", c.ThumbCachePath()},
{"import-path", c.ImportPath()}, {"import-path", c.ImportPath()},
{"import-dest", c.ImportDest()},
{"assets-path", c.AssetsPath()}, {"assets-path", c.AssetsPath()},
{"static-path", c.StaticPath()}, {"static-path", c.StaticPath()},
{"build-path", c.BuildPath()}, {"build-path", c.BuildPath()},

View File

@@ -48,6 +48,7 @@ type Options struct {
BackupPath string `yaml:"BackupPath" json:"-" flag:"backup-path"` BackupPath string `yaml:"BackupPath" json:"-" flag:"backup-path"`
CachePath string `yaml:"CachePath" json:"-" flag:"cache-path"` CachePath string `yaml:"CachePath" json:"-" flag:"cache-path"`
ImportPath string `yaml:"ImportPath" json:"-" flag:"import-path"` ImportPath string `yaml:"ImportPath" json:"-" flag:"import-path"`
ImportDest string `yaml:"ImportDest" json:"-" flag:"import-dest"`
AssetsPath string `yaml:"AssetsPath" json:"-" flag:"assets-path"` AssetsPath string `yaml:"AssetsPath" json:"-" flag:"assets-path"`
CustomAssetsPath string `yaml:"-" json:"-" flag:"custom-assets-path"` CustomAssetsPath string `yaml:"-" json:"-" flag:"custom-assets-path"`
TempPath string `yaml:"TempPath" json:"-" flag:"temp-path"` TempPath string `yaml:"TempPath" json:"-" flag:"temp-path"`

View File

@@ -164,6 +164,12 @@ var Flags = CliFlags{
Usage: "base `PATH` from which files can be imported to originals*optional*", Usage: "base `PATH` from which files can be imported to originals*optional*",
EnvVar: "PHOTOPRISM_IMPORT_PATH", EnvVar: "PHOTOPRISM_IMPORT_PATH",
}}, }},
CliFlag{
Flag: cli.StringFlag{
Name: "import-dest",
Usage: "relative originals `PATH` to which the files should be imported by default*optional*",
EnvVar: "PHOTOPRISM_IMPORT_DEST",
}},
CliFlag{ CliFlag{
Flag: cli.StringFlag{ Flag: cli.StringFlag{
Name: "assets-path, as", Name: "assets-path, as",

View File

@@ -9,41 +9,41 @@ func (s *Settings) ApplyACL(list acl.ACL, role acl.Role) *Settings {
m := *s m := *s
// Features. // Features.
m.Features.Search = s.Features.Search && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionSearch})
m.Features.Ratings = s.Features.Ratings && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionRate})
m.Features.Reactions = s.Features.Reactions && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionReact})
m.Features.Videos = s.Features.Videos && list.AllowAny(acl.ResourceVideos, role, acl.Permissions{acl.ActionSearch})
m.Features.Albums = s.Features.Albums && list.AllowAny(acl.ResourceAlbums, role, acl.Permissions{acl.ActionView}) m.Features.Albums = s.Features.Albums && list.AllowAny(acl.ResourceAlbums, role, acl.Permissions{acl.ActionView})
m.Features.Favorites = s.Features.Favorites && list.AllowAny(acl.ResourceFavorites, role, acl.Permissions{acl.ActionSearch}) m.Features.Favorites = s.Features.Favorites && list.AllowAny(acl.ResourceFavorites, role, acl.Permissions{acl.ActionSearch})
m.Features.Folders = s.Features.Folders && list.AllowAny(acl.ResourceFolders, role, acl.Permissions{acl.ActionSearch})
m.Features.Labels = s.Features.Labels && list.AllowAny(acl.ResourceLabels, role, acl.Permissions{acl.ActionSearch})
m.Features.Moments = s.Features.Moments && list.AllowAny(acl.ResourceMoments, role, acl.Permissions{acl.ActionSearch}) m.Features.Moments = s.Features.Moments && list.AllowAny(acl.ResourceMoments, role, acl.Permissions{acl.ActionSearch})
m.Features.People = s.Features.People && list.AllowAny(acl.ResourcePeople, role, acl.Permissions{acl.ActionSearch}) m.Features.People = s.Features.People && list.AllowAny(acl.ResourcePeople, role, acl.Permissions{acl.ActionSearch})
m.Features.Labels = s.Features.Labels && list.AllowAny(acl.ResourceLabels, role, acl.Permissions{acl.ActionSearch}) m.Features.Places = s.Features.Places && list.AllowAny(acl.ResourcePlaces, role, acl.Permissions{acl.ActionSearch, acl.ActionView})
m.Features.Places = s.Features.Places && list.AllowAny(acl.ResourcePlaces, role, acl.Permissions{acl.ActionSearch})
m.Features.Folders = s.Features.Folders && list.AllowAny(acl.ResourceFolders, role, acl.Permissions{acl.ActionSearch})
m.Features.Private = s.Features.Private && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.AccessPrivate}) m.Features.Private = s.Features.Private && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.AccessPrivate})
m.Features.Ratings = s.Features.Ratings && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionRate})
m.Features.Reactions = s.Features.Reactions && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionReact})
m.Features.Search = s.Features.Search && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionSearch})
m.Features.Videos = s.Features.Videos && list.AllowAny(acl.ResourceVideos, role, acl.Permissions{acl.ActionSearch})
// Permissions. // Permissions.
m.Features.Edit = s.Features.Edit && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionUpdate})
m.Features.Review = s.Features.Review && list.Allow(acl.ResourcePhotos, role, acl.ActionManage)
m.Features.Archive = s.Features.Archive && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionDelete}) m.Features.Archive = s.Features.Archive && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionDelete})
m.Features.Delete = s.Features.Delete && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionDelete}) m.Features.Delete = s.Features.Delete && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionDelete})
m.Features.Edit = s.Features.Edit && list.AllowAny(acl.ResourcePhotos, role, acl.Permissions{acl.ActionUpdate})
m.Features.Review = s.Features.Review && list.Allow(acl.ResourcePhotos, role, acl.ActionManage)
m.Features.Share = s.Features.Share && list.AllowAny(acl.ResourceShares, role, acl.Permissions{acl.ActionManage}) m.Features.Share = s.Features.Share && list.AllowAny(acl.ResourceShares, role, acl.Permissions{acl.ActionManage})
// Browse, upload and download files. // Browse, upload and download files.
m.Features.Download = s.Features.Download && !s.Download.Disabled && list.Allow(acl.ResourcePhotos, role, acl.ActionDownload)
m.Features.Files = s.Features.Files && list.AllowAny(acl.ResourceFiles, role, acl.Permissions{acl.ActionSearch}) m.Features.Files = s.Features.Files && list.AllowAny(acl.ResourceFiles, role, acl.Permissions{acl.ActionSearch})
m.Features.Upload = s.Features.Upload && list.Allow(acl.ResourcePhotos, role, acl.ActionUpload) m.Features.Upload = s.Features.Upload && list.Allow(acl.ResourcePhotos, role, acl.ActionUpload)
m.Features.Download = s.Features.Download && !s.Download.Disabled && list.Allow(acl.ResourcePhotos, role, acl.ActionDownload)
// Library. // Library.
m.Features.Import = s.Features.Import && list.AllowAny(acl.ResourceFiles, role, acl.Permissions{acl.ActionManage, acl.ActionUpload})
m.Features.Library = s.Features.Library && list.Allow(acl.ResourceFiles, role, acl.ActionManage) m.Features.Library = s.Features.Library && list.Allow(acl.ResourceFiles, role, acl.ActionManage)
m.Features.Import = s.Features.Import && list.Allow(acl.ResourceFiles, role, acl.ActionManage) && list.Allow(acl.ResourcePhotos, role, acl.ActionCreate)
m.Features.Logs = s.Features.Logs && list.Allow(acl.ResourceLogs, role, acl.ActionView) m.Features.Logs = s.Features.Logs && list.Allow(acl.ResourceLogs, role, acl.ActionView)
// Settings. // Settings.
m.Features.Settings = s.Features.Settings && list.Allow(acl.ResourceSettings, role, acl.ActionUpdate)
m.Features.Advanced = s.Features.Advanced && list.Allow(acl.ResourceConfig, role, acl.ActionManage)
m.Features.Sync = s.Features.Sync && list.Allow(acl.ResourceAccounts, role, acl.ActionManage)
m.Features.Account = s.Features.Account && list.Allow(acl.ResourcePassword, role, acl.ActionUpdate) m.Features.Account = s.Features.Account && list.Allow(acl.ResourcePassword, role, acl.ActionUpdate)
m.Features.Advanced = s.Features.Advanced && list.Allow(acl.ResourceConfig, role, acl.ActionManage)
m.Features.Settings = s.Features.Settings && list.Allow(acl.ResourceSettings, role, acl.ActionUpdate)
m.Features.Sync = s.Features.Sync && list.Allow(acl.ResourceAccounts, role, acl.ActionManage)
return &m return &m
} }

View File

@@ -73,7 +73,7 @@ func TestSettings_ApplyACL(t *testing.T) {
Logs: false, Logs: false,
Moments: false, Moments: false,
People: false, People: false,
Places: false, Places: true,
Private: false, Private: false,
Ratings: false, Ratings: false,
Reactions: false, Reactions: false,

View File

@@ -47,10 +47,10 @@ type Account struct {
AccShare bool AccShare bool
AccSync bool AccSync bool
RetryLimit int RetryLimit int
SharePath string `gorm:"type:VARBINARY(500);"` SharePath string `gorm:"type:VARBINARY(1024);"`
ShareSize string `gorm:"type:VARBINARY(16);"` ShareSize string `gorm:"type:VARBINARY(16);"`
ShareExpires int ShareExpires int
SyncPath string `gorm:"type:VARBINARY(500);"` SyncPath string `gorm:"type:VARBINARY(1024);"`
SyncStatus string `gorm:"type:VARBINARY(16);"` SyncStatus string `gorm:"type:VARBINARY(16);"`
SyncInterval int SyncInterval int
SyncDate sql.NullTime `deepcopier:"skip"` SyncDate sql.NullTime `deepcopier:"skip"`

View File

@@ -19,12 +19,12 @@ import (
) )
const ( const (
AlbumUID = byte('a')
AlbumDefault = "album" AlbumDefault = "album"
AlbumFolder = "folder" AlbumFolder = "folder"
AlbumMoment = "moment" AlbumMoment = "moment"
AlbumMonth = "month" AlbumMonth = "month"
AlbumState = "state" AlbumState = "state"
AlbumUID = 'a'
) )
type Albums []Album type Albums []Album
@@ -35,7 +35,7 @@ type Album struct {
AlbumUID string `gorm:"type:VARBINARY(64);unique_index;" json:"UID" yaml:"UID"` AlbumUID string `gorm:"type:VARBINARY(64);unique_index;" json:"UID" yaml:"UID"`
ParentUID string `gorm:"type:VARBINARY(64);default:'';" json:"ParentUID,omitempty" yaml:"ParentUID,omitempty"` ParentUID string `gorm:"type:VARBINARY(64);default:'';" json:"ParentUID,omitempty" yaml:"ParentUID,omitempty"`
AlbumSlug string `gorm:"type:VARBINARY(160);index;" json:"Slug" yaml:"Slug"` AlbumSlug string `gorm:"type:VARBINARY(160);index;" json:"Slug" yaml:"Slug"`
AlbumPath string `gorm:"type:VARBINARY(500);index;" json:"Path,omitempty" yaml:"Path,omitempty"` AlbumPath string `gorm:"type:VARBINARY(1024);index;" json:"Path,omitempty" yaml:"Path,omitempty"`
AlbumType string `gorm:"type:VARBINARY(8);default:'album';" json:"Type" yaml:"Type,omitempty"` AlbumType string `gorm:"type:VARBINARY(8);default:'album';" json:"Type" yaml:"Type,omitempty"`
AlbumTitle string `gorm:"type:VARCHAR(160);index;" json:"Title" yaml:"Title"` AlbumTitle string `gorm:"type:VARCHAR(160);index;" json:"Title" yaml:"Title"`
AlbumLocation string `gorm:"type:VARCHAR(160);" json:"Location" yaml:"Location,omitempty"` AlbumLocation string `gorm:"type:VARCHAR(160);" json:"Location" yaml:"Location,omitempty"`

View File

@@ -20,7 +20,7 @@ func FlushAlbumCache() {
// CachedAlbumByUID returns an existing album or nil if not found. // CachedAlbumByUID returns an existing album or nil if not found.
func CachedAlbumByUID(uid string) (m Album, err error) { func CachedAlbumByUID(uid string) (m Album, err error) {
// Valid album UID? // Valid album UID?
if uid == "" || !rnd.IsUID(uid, 'a') { if uid == "" || rnd.InvalidUID(uid, AlbumUID) {
return m, fmt.Errorf("invalid album uid %s", clean.LogQuote(uid)) return m, fmt.Errorf("invalid album uid %s", clean.LogQuote(uid))
} }

View File

@@ -6,6 +6,9 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
@@ -238,22 +241,27 @@ func (m *Session) SetContext(c *gin.Context) *Session {
return m return m
} }
if ip := txt.Clip(c.ClientIP(), 48); ip != "" { m.SetClientIP(c.ClientIP())
m.ClientIP = net.ParseIP(ip).String() m.SetUserAgent(c.GetHeader("User-Agent"))
if m.LoginIP == "" {
m.LoginIP = net.ParseIP(ip).String()
m.LoginAt = TimeStamp()
}
}
if ua := txt.Clip(c.GetHeader("User-Agent"), 512); ua != "" {
m.UserAgent = ua
}
return m return m
} }
// IsVisitor checks if the session belongs to a sharing link visitor.
func (m *Session) IsVisitor() bool {
return m.User().IsVisitor()
}
// IsRegistered checks if the session belongs to a registered user account.
func (m *Session) IsRegistered() bool {
return m.User().IsRegistered()
}
// Unregistered checks if the session belongs to a unregistered user.
func (m *Session) Unregistered() bool {
return !m.User().IsRegistered()
}
// NoShares checks if the session has no shares yet. // NoShares checks if the session has no shares yet.
func (m *Session) NoShares() bool { func (m *Session) NoShares() bool {
return m.Data().NoShares() return m.Data().NoShares()
@@ -269,11 +277,6 @@ func (m *Session) HasShare(uid string) bool {
return m.Data().HasShare(uid) return m.Data().HasShare(uid)
} }
// IsVisitor checks if the session belongs to a sharing link visitor.
func (m *Session) IsVisitor() bool {
return m.User().IsVisitor()
}
// Expired checks if the session has expired. // Expired checks if the session has expired.
func (m *Session) Expired() bool { func (m *Session) Expired() bool {
if m.ExpiresAt.IsZero() { if m.ExpiresAt.IsZero() {
@@ -320,3 +323,45 @@ func (m *Session) SharedUIDs() UIDs {
return data.SharedUIDs() return data.SharedUIDs()
} }
// SetUserAgent sets the client user agent.
func (m *Session) SetUserAgent(ua string) {
if ua == "" {
return
} else if ua = txt.Clip(ua, 512); ua == "" {
return
} else if m.UserAgent != "" && m.UserAgent != ua {
event.AuditWarn([]string{m.IP(), "session %s", "user agent has changed from %s to %s"}, m.RefID, clean.LogQuote(m.UserAgent), clean.LogQuote(ua))
}
m.UserAgent = ua
}
// SetClientIP sets the client IP address.
func (m *Session) SetClientIP(ip string) {
if ip == "" {
return
} else if parsed := net.ParseIP(ip); parsed == nil {
return
} else if ip = parsed.String(); ip == "" {
return
} else if m.ClientIP != "" && m.ClientIP != ip {
event.AuditWarn([]string{ip, "session %s", "client address has changed from %s to %s"}, m.RefID, clean.LogQuote(m.ClientIP), clean.LogQuote(ip))
}
m.ClientIP = ip
if m.LoginIP == "" {
m.LoginIP = ip
m.LoginAt = TimeStamp()
}
}
// IP returns the client IP address, or "unknown" if it is unknown.
func (m *Session) IP() string {
if m.ClientIP != "" {
return m.ClientIP
} else {
return "unknown"
}
}

View File

@@ -82,6 +82,10 @@ func (data SessionData) HasShares() bool {
// HasShare if the session includes the specified share // HasShare if the session includes the specified share
func (data SessionData) HasShare(uid string) bool { func (data SessionData) HasShare(uid string) bool {
if uid == "" || data.NoShares() {
return false
}
for _, share := range data.Shares { for _, share := range data.Shares {
if share == uid { if share == uid {
return true return true

View File

@@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/mail" "net/mail"
"path"
"strings" "strings"
"time" "time"
@@ -18,8 +19,8 @@ import (
// User identifier prefixes. // User identifier prefixes.
const ( const (
UserUID = byte('u')
UserPrefix = "user" UserPrefix = "user"
UserUID = 'u'
) )
// LenNameMin specifies the minimum length of the username in characters. // LenNameMin specifies the minimum length of the username in characters.
@@ -47,6 +48,8 @@ type User struct {
SuperAdmin bool `json:"SuperAdmin,omitempty" yaml:"SuperAdmin,omitempty"` SuperAdmin bool `json:"SuperAdmin,omitempty" yaml:"SuperAdmin,omitempty"`
CanLogin bool `json:"CanLogin,omitempty" yaml:"CanLogin,omitempty"` CanLogin bool `json:"CanLogin,omitempty" yaml:"CanLogin,omitempty"`
LoginAt *time.Time `json:"LoginAt,omitempty" yaml:"LoginAt,omitempty"` LoginAt *time.Time `json:"LoginAt,omitempty" yaml:"LoginAt,omitempty"`
BasePath string `gorm:"type:VARBINARY(1024);" json:"BasePath,omitempty" yaml:"BasePath,omitempty"`
UploadPath string `gorm:"type:VARBINARY(1024);" json:"UploadPath,omitempty" yaml:"UploadPath,omitempty"`
CanSync bool `json:"CanSync,omitempty" yaml:"CanSync,omitempty"` CanSync bool `json:"CanSync,omitempty" yaml:"CanSync,omitempty"`
CanInvite bool `json:"CanInvite,omitempty" yaml:"CanInvite,omitempty"` CanInvite bool `json:"CanInvite,omitempty" yaml:"CanInvite,omitempty"`
InviteToken string `gorm:"type:VARBINARY(64);index;" json:"-" yaml:"-"` InviteToken string `gorm:"type:VARBINARY(64);index;" json:"-" yaml:"-"`
@@ -277,7 +280,7 @@ func (m *User) Disabled() bool {
return m.Deleted() || m.Expired() return m.Deleted() || m.Expired()
} }
// LoginAllowed checks if logging in with the user account is possible. // LoginAllowed checks if the user is allowed to log in and use the web UI.
func (m *User) LoginAllowed() bool { func (m *User) LoginAllowed() bool {
if role := m.AclRole(); m.Disabled() || !m.CanLogin || m.UserName == "" || role == acl.RoleUnauthorized { if role := m.AclRole(); m.Disabled() || !m.CanLogin || m.UserName == "" || role == acl.RoleUnauthorized {
return false return false
@@ -287,7 +290,7 @@ func (m *User) LoginAllowed() bool {
} }
// SyncAllowed checks if file sync with the user account is possible. // SyncAllowed checks whether the user is allowed to use WebDAV to synchronize files.
func (m *User) SyncAllowed() bool { func (m *User) SyncAllowed() bool {
if role := m.AclRole(); m.Disabled() || !m.CanSync || m.UserName == "" || role == acl.RoleUnauthorized { if role := m.AclRole(); m.Disabled() || !m.CanSync || m.UserName == "" || role == acl.RoleUnauthorized {
return false return false
@@ -296,6 +299,33 @@ func (m *User) SyncAllowed() bool {
} }
} }
// UploadAllowed checks if the user is allowed to upload files.
func (m *User) UploadAllowed() bool {
if role := m.AclRole(); m.Disabled() || role == acl.RoleUnauthorized {
return false
} else {
return acl.Resources.Allow(acl.ResourcePhotos, role, acl.ActionUpload)
}
}
// SetBasePath changes the user's base folder.
func (m *User) SetBasePath(dir string) *User {
m.BasePath = clean.UserPath(dir)
return m
}
// SetUploadPath changes the user's upload folder.
func (m *User) SetUploadPath(dir string) *User {
if m.BasePath == "" {
m.UploadPath = clean.UserPath(dir)
} else {
m.UploadPath = path.Join(m.BasePath, clean.UserPath(dir))
}
return m
}
// String returns an identifier that can be used in logs. // String returns an identifier that can be used in logs.
func (m *User) String() string { func (m *User) String() string {
if n := m.Name(); n != "" { if n := m.Name(); n != "" {
@@ -326,7 +356,7 @@ func (m *User) SetName(login string) (err error) {
// Update display name. // Update display name.
if m.DisplayName == "" || m.DisplayName == AdminDisplayName { if m.DisplayName == "" || m.DisplayName == AdminDisplayName {
m.DisplayName = clean.Name(login) m.DisplayName = clean.NameCapitalized(login)
} }
return nil return nil
@@ -568,6 +598,8 @@ func (m *User) SetFormValues(frm form.User) *User {
m.CanSync = frm.CanSync m.CanSync = frm.CanSync
m.UserRole = frm.Role() m.UserRole = frm.Role()
m.UserAttr = frm.Attr() m.UserAttr = frm.Attr()
m.SetBasePath(frm.BasePath)
m.SetUploadPath(frm.UploadPath)
return m return m
} }

View File

@@ -1,6 +1,7 @@
package entity package entity
import ( import (
"github.com/photoprism/photoprism/pkg/clean"
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
@@ -16,8 +17,8 @@ func (m *User) SetValuesFromCli(ctx *cli.Context) error {
} }
// Display name. // Display name.
if ctx.IsSet("displayname") { if ctx.IsSet("name") {
m.DisplayName = frm.DisplayName m.DisplayName = clean.Name(frm.DisplayName)
} }
// User role. // User role.
@@ -25,18 +26,13 @@ func (m *User) SetValuesFromCli(ctx *cli.Context) error {
m.UserRole = frm.Role() m.UserRole = frm.Role()
} }
// Custom attributes.
if ctx.IsSet("attr") {
m.UserAttr = frm.Attr()
}
// Super-admin status. // Super-admin status.
if ctx.IsSet("superadmin") { if ctx.IsSet("superadmin") {
m.SuperAdmin = frm.SuperAdmin m.SuperAdmin = frm.SuperAdmin
} }
// Disable Web UI? // Disable Web UI?
if ctx.IsSet("disable-login") { if ctx.IsSet("no-login") {
m.CanLogin = frm.CanLogin m.CanLogin = frm.CanLogin
} }
@@ -45,5 +41,20 @@ func (m *User) SetValuesFromCli(ctx *cli.Context) error {
m.CanSync = frm.CanSync m.CanSync = frm.CanSync
} }
// Custom attributes.
if ctx.IsSet("attr") {
m.UserAttr = frm.Attr()
}
// Originals base folder.
if ctx.IsSet("base-path") {
m.SetBasePath(frm.BasePath)
}
// Sub-folder for uploads.
if ctx.IsSet("upload-path") {
m.SetUploadPath(frm.UploadPath)
}
return m.Validate() return m.Validate()
} }

View File

@@ -11,17 +11,17 @@ import (
// UserSettings represents user preferences. // UserSettings represents user preferences.
type UserSettings struct { type UserSettings struct {
UserUID string `gorm:"type:VARBINARY(64);primary_key;auto_increment:false;" json:"-" yaml:"UserUID"` UserUID string `gorm:"type:VARBINARY(64);primary_key;auto_increment:false;" json:"-" yaml:"UserUID"`
UIHome string `gorm:"type:VARBINARY(32);column:ui_home;" json:"UIHome,omitempty" yaml:"UIHome,omitempty"`
UITheme string `gorm:"type:VARBINARY(32);column:ui_theme;" json:"UITheme,omitempty" yaml:"UITheme,omitempty"` UITheme string `gorm:"type:VARBINARY(32);column:ui_theme;" json:"UITheme,omitempty" yaml:"UITheme,omitempty"`
UILanguage string `gorm:"type:VARBINARY(32);column:ui_language;" json:"UILanguage,omitempty" yaml:"UILanguage,omitempty"` UILanguage string `gorm:"type:VARBINARY(32);column:ui_language;" json:"UILanguage,omitempty" yaml:"UILanguage,omitempty"`
UITimeZone string `gorm:"type:VARBINARY(64);column:ui_time_zone;" json:"UITimeZone,omitempty" yaml:"UITimeZone,omitempty"` UITimeZone string `gorm:"type:VARBINARY(64);column:ui_time_zone;" json:"UITimeZone,omitempty" yaml:"UITimeZone,omitempty"`
MapsStyle string `gorm:"type:VARBINARY(32);" json:"MapsStyle,omitempty" yaml:"MapsStyle,omitempty"` MapsStyle string `gorm:"type:VARBINARY(32);" json:"MapsStyle,omitempty" yaml:"MapsStyle,omitempty"`
MapsAnimate int `json:"MapsAnimate,omitempty" yaml:"MapsAnimate,omitempty"` MapsAnimate int `json:"MapsAnimate,omitempty" yaml:"MapsAnimate,omitempty"`
IndexPath string `gorm:"type:VARBINARY(500);" json:"IndexPath,omitempty" yaml:"IndexPath,omitempty"` IndexPath string `gorm:"type:VARBINARY(1024);" json:"IndexPath,omitempty" yaml:"IndexPath,omitempty"`
IndexRescan int `json:"IndexRescan,omitempty" yaml:"IndexRescan,omitempty"` IndexRescan int `json:"IndexRescan,omitempty" yaml:"IndexRescan,omitempty"`
ImportPath string `gorm:"type:VARBINARY(500);" json:"ImportPath,omitempty" yaml:"ImportPath,omitempty"` ImportPath string `gorm:"type:VARBINARY(1024);" json:"ImportPath,omitempty" yaml:"ImportPath,omitempty"`
ImportMove int `json:"ImportMove,omitempty" yaml:"ImportMove,omitempty"` ImportMove int `json:"ImportMove,omitempty" yaml:"ImportMove,omitempty"`
UploadPath string `gorm:"type:VARBINARY(500);" json:"UploadPath,omitempty" yaml:"UploadPath,omitempty"` UploadPath string `gorm:"type:VARBINARY(1024);" json:"UploadPath,omitempty" yaml:"UploadPath,omitempty"`
DefaultPage string `gorm:"type:VARBINARY(128);" json:"DefaultPage,omitempty" yaml:"DefaultPage,omitempty"`
CreatedAt time.Time `json:"CreatedAt" yaml:"-"` CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"` UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
} }

View File

@@ -665,3 +665,9 @@ func TestUser_SyncAllowed(t *testing.T) {
assert.False(t, UserFixtures.Pointer("deleted").SyncAllowed()) assert.False(t, UserFixtures.Pointer("deleted").SyncAllowed())
assert.False(t, UserFixtures.Pointer("friend").SyncAllowed()) assert.False(t, UserFixtures.Pointer("friend").SyncAllowed())
} }
func TestUser_UploadAllowed(t *testing.T) {
assert.True(t, UserFixtures.Pointer("alice").UploadAllowed())
assert.False(t, UserFixtures.Pointer("deleted").UploadAllowed())
assert.True(t, UserFixtures.Pointer("friend").UploadAllowed())
}

View File

@@ -250,7 +250,7 @@ func FirstOrCreateCell(m *Cell) *Cell {
// Keywords returns search keywords for a location. // Keywords returns search keywords for a location.
func (m *Cell) Keywords() (result []string) { func (m *Cell) Keywords() (result []string) {
if m.Place == nil { if m.Place == nil {
log.Errorf("cell: info for %s is nil - possible bug", m.ID) log.Errorf("cell: place for %s is missing - possible bug", m.ID)
return result return result
} }

View File

@@ -411,7 +411,7 @@ func FindFace(id string) *Face {
// ValidFaceCount counts the number of valid face markers for a file uid. // ValidFaceCount counts the number of valid face markers for a file uid.
func ValidFaceCount(fileUID string) (c int) { func ValidFaceCount(fileUID string) (c int) {
if !rnd.IsUID(fileUID, 'f') { if !rnd.IsUID(fileUID, FileUID) {
return return
} }

View File

@@ -25,6 +25,10 @@ import (
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )
const (
FileUID = byte('f')
)
// Files represents a file result set. // Files represents a file result set.
type Files []File type Files []File
@@ -44,7 +48,7 @@ type File struct {
MediaUTC int64 `gorm:"column:media_utc;index;" json:"MediaUTC" yaml:"MediaUTC,omitempty"` MediaUTC int64 `gorm:"column:media_utc;index;" json:"MediaUTC" yaml:"MediaUTC,omitempty"`
InstanceID string `gorm:"type:VARBINARY(64);index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"` InstanceID string `gorm:"type:VARBINARY(64);index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"`
FileUID string `gorm:"type:VARBINARY(64);unique_index;" json:"UID" yaml:"UID"` FileUID string `gorm:"type:VARBINARY(64);unique_index;" json:"UID" yaml:"UID"`
FileName string `gorm:"type:VARBINARY(755);unique_index:idx_files_name_root;" json:"Name" yaml:"Name"` FileName string `gorm:"type:VARBINARY(1024);unique_index:idx_files_name_root;" json:"Name" yaml:"Name"`
FileRoot string `gorm:"type:VARBINARY(16);default:'/';unique_index:idx_files_name_root;" json:"Root" yaml:"Root,omitempty"` FileRoot string `gorm:"type:VARBINARY(16);default:'/';unique_index:idx_files_name_root;" json:"Root" yaml:"Root,omitempty"`
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"` OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
FileHash string `gorm:"type:VARBINARY(128);index" json:"Hash" yaml:"Hash,omitempty"` FileHash string `gorm:"type:VARBINARY(128);index" json:"Hash" yaml:"Hash,omitempty"`
@@ -193,11 +197,11 @@ func (m *File) BeforeCreate(scope *gorm.Scope) error {
} }
// Return if uid exists. // Return if uid exists.
if rnd.IsUnique(m.FileUID, 'f') { if rnd.IsUnique(m.FileUID, FileUID) {
return nil return nil
} }
return scope.SetColumn("FileUID", rnd.GenerateUID('f')) return scope.SetColumn("FileUID", rnd.GenerateUID(FileUID))
} }
// DownloadName returns the download file name. // DownloadName returns the download file name.

View File

@@ -22,7 +22,7 @@ type Folders []Folder
// Folder represents a file system directory. // Folder represents a file system directory.
type Folder struct { type Folder struct {
Path string `gorm:"type:VARBINARY(500);unique_index:idx_folders_path_root;" json:"Path" yaml:"Path"` Path string `gorm:"type:VARBINARY(1024);unique_index:idx_folders_path_root;" json:"Path" yaml:"Path"`
Root string `gorm:"type:VARBINARY(16);default:'';unique_index:idx_folders_path_root;" json:"Root" yaml:"Root,omitempty"` Root string `gorm:"type:VARBINARY(16);default:'';unique_index:idx_folders_path_root;" json:"Root" yaml:"Root,omitempty"`
FolderUID string `gorm:"type:VARBINARY(64);primary_key;" json:"UID,omitempty" yaml:"UID,omitempty"` FolderUID string `gorm:"type:VARBINARY(64);primary_key;" json:"UID,omitempty" yaml:"UID,omitempty"`
FolderType string `gorm:"type:VARBINARY(16);" json:"Type" yaml:"Type,omitempty"` FolderType string `gorm:"type:VARBINARY(16);" json:"Type" yaml:"Type,omitempty"`

View File

@@ -14,6 +14,10 @@ import (
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )
const (
LabelUID = byte('l')
)
var labelMutex = sync.Mutex{} var labelMutex = sync.Mutex{}
var labelCategoriesMutex = sync.Mutex{} var labelCategoriesMutex = sync.Mutex{}
@@ -47,11 +51,11 @@ func (Label) TableName() string {
// BeforeCreate creates a random UID if needed before inserting a new row to the database. // BeforeCreate creates a random UID if needed before inserting a new row to the database.
func (m *Label) BeforeCreate(scope *gorm.Scope) error { func (m *Label) BeforeCreate(scope *gorm.Scope) error {
if rnd.IsUnique(m.LabelUID, 'l') { if rnd.IsUnique(m.LabelUID, LabelUID) {
return nil return nil
} }
return scope.SetColumn("LabelUID", rnd.GenerateUID('l')) return scope.SetColumn("LabelUID", rnd.GenerateUID(LabelUID))
} }
// NewLabel returns a new label. // NewLabel returns a new label.
@@ -168,7 +172,7 @@ func (m *Label) AfterCreate(scope *gorm.Scope) error {
// SetName changes the label name. // SetName changes the label name.
func (m *Label) SetName(name string) { func (m *Label) SetName(name string) {
name = clean.Name(name) name = clean.NameCapitalized(name)
if name == "" { if name == "" {
return return

View File

@@ -11,6 +11,10 @@ import (
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )
const (
LinkUID = byte('s')
)
type Links []Link type Links []Link
// Link represents a sharing link. // Link represents a sharing link.
@@ -36,11 +40,11 @@ func (Link) TableName() string {
// BeforeCreate creates a random UID if needed before inserting a new row to the database. // BeforeCreate creates a random UID if needed before inserting a new row to the database.
func (m *Link) BeforeCreate(scope *gorm.Scope) error { func (m *Link) BeforeCreate(scope *gorm.Scope) error {
if rnd.IsUnique(m.LinkUID, 's') { if rnd.IsUnique(m.LinkUID, LinkUID) {
return nil return nil
} }
return scope.SetColumn("LinkUID", rnd.GenerateUID('s')) return scope.SetColumn("LinkUID", rnd.GenerateUID(LinkUID))
} }
// NewLink creates a sharing link. // NewLink creates a sharing link.
@@ -48,7 +52,7 @@ func NewLink(shareUID string, canComment, canEdit bool) Link {
now := TimeStamp() now := TimeStamp()
result := Link{ result := Link{
LinkUID: rnd.GenerateUID('s'), LinkUID: rnd.GenerateUID(LinkUID),
ShareUID: shareUID, ShareUID: shareUID,
LinkToken: rnd.GenerateToken(10), LinkToken: rnd.GenerateToken(10),
CanComment: canComment, CanComment: canComment,

View File

@@ -23,7 +23,7 @@ import (
) )
const ( const (
PhotoUID = 'p' PhotoUID = byte('p')
) )
var MetadataUpdateInterval = 24 * 3 * time.Hour // 3 Days var MetadataUpdateInterval = 24 * 3 * time.Hour // 3 Days
@@ -63,7 +63,7 @@ type Photo struct {
TitleSrc string `gorm:"type:VARBINARY(8);" json:"TitleSrc" yaml:"TitleSrc,omitempty"` TitleSrc string `gorm:"type:VARBINARY(8);" json:"TitleSrc" yaml:"TitleSrc,omitempty"`
PhotoDescription string `gorm:"type:VARCHAR(4096);" json:"Description" yaml:"Description,omitempty"` PhotoDescription string `gorm:"type:VARCHAR(4096);" json:"Description" yaml:"Description,omitempty"`
DescriptionSrc string `gorm:"type:VARBINARY(8);" json:"DescriptionSrc" yaml:"DescriptionSrc,omitempty"` DescriptionSrc string `gorm:"type:VARBINARY(8);" json:"DescriptionSrc" yaml:"DescriptionSrc,omitempty"`
PhotoPath string `gorm:"type:VARBINARY(500);index:idx_photos_path_name;" json:"Path" yaml:"-"` PhotoPath string `gorm:"type:VARBINARY(1024);index:idx_photos_path_name;" json:"Path" yaml:"-"`
PhotoName string `gorm:"type:VARBINARY(255);index:idx_photos_path_name;" json:"Name" yaml:"-"` PhotoName string `gorm:"type:VARBINARY(255);index:idx_photos_path_name;" json:"Name" yaml:"-"`
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"` OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
PhotoStack int8 `json:"Stack" yaml:"Stack,omitempty"` PhotoStack int8 `json:"Stack" yaml:"Stack,omitempty"`

View File

@@ -9,8 +9,9 @@ import (
// SearchPhotos represents search form fields for "/api/v1/photos". // SearchPhotos represents search form fields for "/api/v1/photos".
type SearchPhotos struct { type SearchPhotos struct {
Query string `form:"q"` Query string `form:"q"`
Filter string `form:"filter" notes:"-" serialize:"-"` In string `form:"in" serialize:"-" example:"in:ariqwb43p5dh9h13" notes:"Limits results to the album UID specified"`
UID string `form:"uid" example:"uid:pqbcf5j446s0futy" notes:"Internal Unique ID, only exact matches"` Filter string `form:"filter" serialize:"-" notes:"-"`
UID string `form:"uid" example:"uid:pqbcf5j446s0futy" notes:"Search for specific files or photos, only exact matches"`
Type string `form:"type" example:"type:raw" notes:"Media Type (image, video, raw, live, animated); OR search with |"` Type string `form:"type" example:"type:raw" notes:"Media Type (image, video, raw, live, animated); OR search with |"`
Path string `form:"path" example:"path:2020/Holiday" notes:"Path Name, OR search with |, supports * wildcards"` Path string `form:"path" example:"path:2020/Holiday" notes:"Path Name, OR search with |, supports * wildcards"`
Folder string `form:"folder" example:"folder:\"*/2020\"" notes:"Path Name, OR search with |, supports * wildcards"` // Alias for Path Folder string `form:"folder" example:"folder:\"*/2020\"" notes:"Path Name, OR search with |, supports * wildcards"` // Alias for Path
@@ -138,6 +139,11 @@ func (f *SearchPhotos) SerializeAll() string {
return Serialize(f, true) return Serialize(f, true)
} }
// FindUidOnly checks if search filters other than UID may be skipped to improve performance.
func (f *SearchPhotos) FindUidOnly() bool {
return f.UID != "" && f.Query == "" && f.In == "" && f.Filter == "" && f.Album == "" && f.Albums == ""
}
func NewPhotoSearch(query string) SearchPhotos { func NewPhotoSearch(query string) SearchPhotos {
return SearchPhotos{Query: query} return SearchPhotos{Query: query}
} }

View File

@@ -9,7 +9,9 @@ import (
// SearchPhotosGeo represents search form fields for "/api/v1/geo". // SearchPhotosGeo represents search form fields for "/api/v1/geo".
type SearchPhotosGeo struct { type SearchPhotosGeo struct {
Query string `form:"q"` Query string `form:"q"`
Filter string `form:"filter"` In string `form:"in" serialize:"-" example:"in:ariqwb43p5dh9h13" notes:"Limits results to the album UID specified"`
Filter string `form:"filter" serialize:"-" notes:"-"`
UID string `form:"uid" example:"uid:pqbcf5j446s0futy" notes:"Search for specific files or photos, only exact matches"`
Near string `form:"near"` Near string `form:"near"`
Type string `form:"type"` Type string `form:"type"`
Path string `form:"path"` Path string `form:"path"`
@@ -48,8 +50,8 @@ type SearchPhotosGeo struct {
Subjects string `form:"subjects"` // Text Subjects string `form:"subjects"` // Text
People string `form:"people"` // Alias for Subjects People string `form:"people"` // Alias for Subjects
Keywords string `form:"keywords"` Keywords string `form:"keywords"`
Album string `form:"album"` Album string `form:"album" example:"album:berlin" notes:"Album UID or Name, supports * wildcards"`
Albums string `form:"albums"` Albums string `form:"albums" example:"albums:\"South Africa & Birds\"" notes:"Album Names, can be combined with & and |"`
Country string `form:"country"` Country string `form:"country"`
State string `form:"state"` // Moments State string `form:"state"` // Moments
City string `form:"city"` City string `form:"city"`
@@ -122,6 +124,11 @@ func (f *SearchPhotosGeo) SerializeAll() string {
return Serialize(f, true) return Serialize(f, true)
} }
// FindByIdOnly checks if search filters other than UID may be skipped to improve performance.
func (f *SearchPhotosGeo) FindByIdOnly() bool {
return f.UID != "" && f.Query == "" && f.In == "" && f.Filter == "" && f.Album == "" && f.Albums == ""
}
func NewGeoSearch(query string) SearchPhotosGeo { func NewGeoSearch(query string) SearchPhotosGeo {
return SearchPhotosGeo{Query: query} return SearchPhotosGeo{Query: query}
} }

View File

@@ -8,9 +8,9 @@ import (
"time" "time"
"unicode" "unicode"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/araddon/dateparse" "github.com/araddon/dateparse"
"github.com/photoprism/photoprism/pkg/clean"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
) )
@@ -35,7 +35,7 @@ func Serialize(f interface{}, all bool) string {
fieldInfo := v.Type().Field(i).Tag.Get("serialize") fieldInfo := v.Type().Field(i).Tag.Get("serialize")
// Serialize field values as string. // Serialize field values as string.
if fieldName != "" && (fieldInfo != "-" || all) { if fieldName != "" && fieldName != "-" && (fieldInfo != "-" || all) {
switch t := fieldValue.Interface().(type) { switch t := fieldValue.Interface().(type) {
case time.Time: case time.Time:
if val := fieldValue.Interface().(time.Time); !val.IsZero() { if val := fieldValue.Interface().(time.Time); !val.IsZero() {
@@ -123,7 +123,7 @@ func Unserialize(f SearchForm, q string) (result error) {
stringValue := string(value) stringValue := string(value)
if fieldName != "" && field.CanSet() { if fieldName != "" && fieldName != "-" && field.CanSet() {
switch field.Interface().(type) { switch field.Interface().(type) {
case time.Time: case time.Time:
if timeValue, err := dateparse.ParseAny(stringValue); err != nil { if timeValue, err := dateparse.ParseAny(stringValue); err != nil {

View File

@@ -12,10 +12,12 @@ type User struct {
UserEmail string `json:"Email,omitempty" yaml:"Email,omitempty"` UserEmail string `json:"Email,omitempty" yaml:"Email,omitempty"`
DisplayName string `json:"DisplayName,omitempty" yaml:"DisplayName,omitempty"` DisplayName string `json:"DisplayName,omitempty" yaml:"DisplayName,omitempty"`
UserRole string `json:"Role,omitempty" yaml:"Role,omitempty"` UserRole string `json:"Role,omitempty" yaml:"Role,omitempty"`
UserAttr string `json:"Attr,omitempty" yaml:"Attr,omitempty"`
SuperAdmin bool `json:"SuperAdmin,omitempty" yaml:"SuperAdmin,omitempty"` SuperAdmin bool `json:"SuperAdmin,omitempty" yaml:"SuperAdmin,omitempty"`
CanLogin bool `json:"CanLogin,omitempty" yaml:"CanLogin,omitempty"` CanLogin bool `json:"CanLogin,omitempty" yaml:"CanLogin,omitempty"`
CanSync bool `json:"CanSync,omitempty" yaml:"CanSync,omitempty"` CanSync bool `json:"CanSync,omitempty" yaml:"CanSync,omitempty"`
UserAttr string `json:"Attr,omitempty" yaml:"Attr,omitempty"`
BasePath string `json:"BasePath,omitempty" yaml:"BasePath,omitempty"`
UploadPath string `json:"UploadPath,omitempty" yaml:"UploadPath,omitempty"`
Password string `json:"Password,omitempty" yaml:"Password,omitempty"` Password string `json:"Password,omitempty" yaml:"Password,omitempty"`
} }
@@ -24,12 +26,14 @@ func NewUserFromCli(ctx *cli.Context) User {
return User{ return User{
UserName: clean.Username(ctx.Args().First()), UserName: clean.Username(ctx.Args().First()),
UserEmail: clean.Email(ctx.String("email")), UserEmail: clean.Email(ctx.String("email")),
DisplayName: clean.Name(ctx.String("displayname")), DisplayName: clean.Name(ctx.String("name")),
UserRole: clean.Role(ctx.String("role")), UserRole: clean.Role(ctx.String("role")),
UserAttr: clean.Attr(ctx.String("attr")),
SuperAdmin: ctx.Bool("superadmin"), SuperAdmin: ctx.Bool("superadmin"),
CanLogin: !ctx.Bool("disable-login"), CanLogin: !ctx.Bool("no-login"),
CanSync: ctx.Bool("can-sync"), CanSync: ctx.Bool("can-sync"),
UserAttr: clean.Attr(ctx.String("attr")),
BasePath: clean.Path(ctx.String("base-path")),
UploadPath: clean.Path(ctx.String("upload-path")),
Password: clean.Password(ctx.String("password")), Password: clean.Password(ctx.String("password")),
} }
} }

View File

@@ -105,7 +105,7 @@ var Messages = MessageMap{
ErrPublic: gettext("Not available in public mode"), ErrPublic: gettext("Not available in public mode"),
ErrReadOnly: gettext("Not available in read-only mode"), ErrReadOnly: gettext("Not available in read-only mode"),
ErrUnauthorized: gettext("Please log in to your account"), ErrUnauthorized: gettext("Please log in to your account"),
ErrForbidden: gettext("Access denied"), ErrForbidden: gettext("Permission denied"),
ErrOffensiveUpload: gettext("Upload might be offensive"), ErrOffensiveUpload: gettext("Upload might be offensive"),
ErrNoItemsSelected: gettext("No items selected"), ErrNoItemsSelected: gettext("No items selected"),
ErrCreateFile: gettext("Failed creating file, please check permissions"), ErrCreateFile: gettext("Failed creating file, please check permissions"),

View File

@@ -8,7 +8,7 @@ var conf *config.Config
func SetConfig(c *config.Config) { func SetConfig(c *config.Config) {
if c == nil { if c == nil {
panic("config is nil") panic("config is missing")
} }
conf = c conf = c
@@ -16,7 +16,7 @@ func SetConfig(c *config.Config) {
func Config() *config.Config { func Config() *config.Config {
if conf == nil { if conf == nil {
panic("config is nil") panic("config is missing")
} }
return conf return conf

View File

@@ -61,7 +61,7 @@ func (imp *Import) Start(opt ImportOptions) fs.Done {
done := make(fs.Done) done := make(fs.Done)
if imp.conf == nil { if imp.conf == nil {
log.Errorf("import: config is nil") log.Errorf("import: config is not set")
return done return done
} }
@@ -273,7 +273,7 @@ func (imp *Import) Cancel() {
} }
// DestinationFilename returns the destination filename of a MediaFile to be imported. // DestinationFilename returns the destination filename of a MediaFile to be imported.
func (imp *Import) DestinationFilename(mainFile *MediaFile, mediaFile *MediaFile) (string, error) { func (imp *Import) DestinationFilename(mainFile *MediaFile, mediaFile *MediaFile, folder string) (string, error) {
fileName := mainFile.CanonicalName() fileName := mainFile.CanonicalName()
fileExtension := mediaFile.Extension() fileExtension := mediaFile.Extension()
dateCreated := mainFile.DateCreated() dateCreated := mainFile.DateCreated()
@@ -289,11 +289,9 @@ func (imp *Import) DestinationFilename(mainFile *MediaFile, mediaFile *MediaFile
} }
} }
// Mon Jan 2 15:04:05 -0700 MST 2006 // Find and return available filename.
pathName := filepath.Join(imp.originalsPath(), dateCreated.Format("2006/01"))
iteration := 0 iteration := 0
pathName := filepath.Join(imp.originalsPath(), folder, dateCreated.Format("2006/01"))
result := filepath.Join(pathName, fileName+fileExtension) result := filepath.Join(pathName, fileName+fileExtension)
for fs.FileExists(result) { for fs.FileExists(result) {

View File

@@ -1,19 +1,22 @@
package photoprism package photoprism
// ImportOptions represents file import options.
type ImportOptions struct { type ImportOptions struct {
Albums []string Albums []string
Path string Path string
Move bool Move bool
DestFolder string
RemoveDotFiles bool RemoveDotFiles bool
RemoveExistingFiles bool RemoveExistingFiles bool
RemoveEmptyDirectories bool RemoveEmptyDirectories bool
} }
// ImportOptionsCopy returns import options for copying files to originals (read-only). // ImportOptionsCopy returns import options for copying files to originals (read-only).
func ImportOptionsCopy(path string) ImportOptions { func ImportOptionsCopy(importPath, destFolder string) ImportOptions {
result := ImportOptions{ result := ImportOptions{
Path: path, Path: importPath,
Move: false, Move: false,
DestFolder: destFolder,
RemoveDotFiles: false, RemoveDotFiles: false,
RemoveExistingFiles: false, RemoveExistingFiles: false,
RemoveEmptyDirectories: false, RemoveEmptyDirectories: false,
@@ -23,10 +26,11 @@ func ImportOptionsCopy(path string) ImportOptions {
} }
// ImportOptionsMove returns import options for moving files to originals (modifies import directory). // ImportOptionsMove returns import options for moving files to originals (modifies import directory).
func ImportOptionsMove(path string) ImportOptions { func ImportOptionsMove(importPath, destFolder string) ImportOptions {
result := ImportOptions{ result := ImportOptions{
Path: path, Path: importPath,
Move: true, Move: true,
DestFolder: destFolder,
RemoveDotFiles: true, RemoveDotFiles: true,
RemoveExistingFiles: true, RemoveExistingFiles: true,
RemoveEmptyDirectories: true, RemoveEmptyDirectories: true,

View File

@@ -7,19 +7,43 @@ import (
) )
func TestImportOptionsCopy(t *testing.T) { func TestImportOptionsCopy(t *testing.T) {
result := ImportOptionsCopy("xxx") t.Run("Default", func(t *testing.T) {
result := ImportOptionsCopy("xxx", "")
assert.Equal(t, "xxx", result.Path) assert.Equal(t, "xxx", result.Path)
assert.Equal(t, "", result.DestFolder)
assert.Equal(t, false, result.Move) assert.Equal(t, false, result.Move)
assert.Equal(t, false, result.RemoveDotFiles) assert.Equal(t, false, result.RemoveDotFiles)
assert.Equal(t, false, result.RemoveExistingFiles) assert.Equal(t, false, result.RemoveExistingFiles)
assert.Equal(t, false, result.RemoveEmptyDirectories) assert.Equal(t, false, result.RemoveEmptyDirectories)
})
t.Run("WithDestPath", func(t *testing.T) {
result := ImportOptionsCopy("xxx", "foo/bar")
assert.Equal(t, "xxx", result.Path)
assert.Equal(t, "foo/bar", result.DestFolder)
assert.Equal(t, false, result.Move)
assert.Equal(t, false, result.RemoveDotFiles)
assert.Equal(t, false, result.RemoveExistingFiles)
assert.Equal(t, false, result.RemoveEmptyDirectories)
})
} }
func TestImportOptionsMove(t *testing.T) { func TestImportOptionsMove(t *testing.T) {
result := ImportOptionsMove("xxx") t.Run("Default", func(t *testing.T) {
result := ImportOptionsMove("xxx", "")
assert.Equal(t, "xxx", result.Path) assert.Equal(t, "xxx", result.Path)
assert.Equal(t, "", result.DestFolder)
assert.Equal(t, true, result.Move) assert.Equal(t, true, result.Move)
assert.Equal(t, true, result.RemoveDotFiles) assert.Equal(t, true, result.RemoveDotFiles)
assert.Equal(t, true, result.RemoveExistingFiles) assert.Equal(t, true, result.RemoveExistingFiles)
assert.Equal(t, true, result.RemoveEmptyDirectories) assert.Equal(t, true, result.RemoveEmptyDirectories)
})
t.Run("WithDestPath", func(t *testing.T) {
result := ImportOptionsMove("xxx", "foo/bar")
assert.Equal(t, "xxx", result.Path)
assert.Equal(t, "foo/bar", result.DestFolder)
assert.Equal(t, true, result.Move)
assert.Equal(t, true, result.RemoveDotFiles)
assert.Equal(t, true, result.RemoveExistingFiles)
assert.Equal(t, true, result.RemoveEmptyDirectories)
})
} }

View File

@@ -27,7 +27,9 @@ func TestNewImport(t *testing.T) {
func TestImport_DestinationFilename(t *testing.T) { func TestImport_DestinationFilename(t *testing.T) {
conf := config.TestConfig() conf := config.TestConfig()
conf.InitializeTestData() if err := conf.InitializeTestData(); err != nil {
t.Fatal(err)
}
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow()) tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath()) nd := nsfw.New(conf.NSFWModelPath())
@@ -44,13 +46,25 @@ func TestImport_DestinationFilename(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
fileName, err := imp.DestinationFilename(rawFile, rawFile) t.Run("NoBasePath", func(t *testing.T) {
fileName, err := imp.DestinationFilename(rawFile, rawFile, "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, conf.OriginalsPath()+"/2019/07/20190705_153230_C167C6FD.cr2", fileName) assert.Equal(t, conf.OriginalsPath()+"/2019/07/20190705_153230_C167C6FD.cr2", fileName)
})
t.Run("WithBasePath", func(t *testing.T) {
fileName, err := imp.DestinationFilename(rawFile, rawFile, "users/guest")
if err != nil {
t.Fatal(err)
}
assert.Equal(t, conf.OriginalsPath()+"/users/guest/2019/07/20190705_153230_C167C6FD.cr2", fileName)
})
} }
func TestImport_Start(t *testing.T) { func TestImport_Start(t *testing.T) {
@@ -71,7 +85,7 @@ func TestImport_Start(t *testing.T) {
imp := NewImport(conf, ind, convert) imp := NewImport(conf, ind, convert)
opt := ImportOptionsMove(conf.ImportPath()) opt := ImportOptionsMove(conf.ImportPath(), "")
imp.Start(opt) imp.Start(opt)
} }

View File

@@ -25,16 +25,18 @@ func ImportWorker(jobs <-chan ImportJob) {
var destMainFileName string var destMainFileName string
o := job.IndexOpt o := job.IndexOpt
imp := job.Imp imp := job.Imp
impOpt := job.ImportOpt opt := job.ImportOpt
impPath := job.ImportOpt.Path src := job.ImportOpt.Path
related := job.Related related := job.Related
// relatedOriginalNames contains the original filenames of related files. // relatedOriginalNames contains the original filenames of related files.
relatedOriginalNames := make(map[string]string, len(related.Files)) relatedOriginalNames := make(map[string]string, len(related.Files))
if related.Main == nil { if related.Main == nil {
log.Warnf("import: %s belongs to no supported media file", clean.Log(fs.RelName(job.FileName, impPath))) log.Warnf("import: %s belongs to no supported media file", clean.Log(fs.RelName(job.FileName, src)))
continue continue
} }
@@ -50,17 +52,18 @@ func ImportWorker(jobs <-chan ImportJob) {
} }
} }
originalName := related.Main.RelName(impPath) originalName := related.Main.RelName(src)
event.Publish("import.file", event.Data{ event.Publish("import.file", event.Data{
"fileName": originalName, "fileName": originalName,
"baseName": filepath.Base(related.Main.FileName()), "baseName": filepath.Base(related.Main.FileName()),
"subFolder": opt.DestFolder,
}) })
for _, f := range related.Files { for _, f := range related.Files {
relFileName := f.RelName(impPath) relFileName := f.RelName(src)
if destFileName, err := imp.DestinationFilename(related.Main, f); err == nil { if destFileName, err := imp.DestinationFilename(related.Main, f, opt.DestFolder); err == nil {
destDir := filepath.Dir(destFileName) destDir := filepath.Dir(destFileName)
// Remember the original filenames of related files, so they can later be indexed and searched. // Remember the original filenames of related files, so they can later be indexed and searched.
@@ -87,7 +90,7 @@ func ImportWorker(jobs <-chan ImportJob) {
log.Infof("import: moving related %s file %s to %s", f.FileType(), clean.Log(relFileName), clean.Log(fs.RelName(destFileName, imp.originalsPath()))) log.Infof("import: moving related %s file %s to %s", f.FileType(), clean.Log(relFileName), clean.Log(fs.RelName(destFileName, imp.originalsPath())))
} }
if impOpt.Move { if opt.Move {
if err := f.Move(destFileName); err != nil { if err := f.Move(destFileName); err != nil {
logRelName := clean.Log(fs.RelName(destMainFileName, imp.originalsPath())) logRelName := clean.Log(fs.RelName(destMainFileName, imp.originalsPath()))
log.Debugf("import: %s", err.Error()) log.Debugf("import: %s", err.Error())
@@ -108,12 +111,12 @@ func ImportWorker(jobs <-chan ImportJob) {
// Do nothing. // Do nothing.
} else if file, err := entity.FirstFileByHash(fileHash); err != nil { } else if file, err := entity.FirstFileByHash(fileHash); err != nil {
// Do nothing. // Do nothing.
} else if err := entity.AddPhotoToAlbums(file.PhotoUID, impOpt.Albums); err != nil { } else if err := entity.AddPhotoToAlbums(file.PhotoUID, opt.Albums); err != nil {
log.Warn(err) log.Warn(err)
} }
// Remove duplicates to save storage. // Remove duplicates to save storage.
if impOpt.RemoveExistingFiles { if opt.RemoveExistingFiles {
if err := f.Remove(); err != nil { if err := f.Remove(); err != nil {
log.Errorf("import: failed deleting %s (%s)", clean.Log(f.BaseName()), err.Error()) log.Errorf("import: failed deleting %s (%s)", clean.Log(f.BaseName()), err.Error())
} else { } else {
@@ -201,7 +204,7 @@ func ImportWorker(jobs <-chan ImportJob) {
photoUID = res.PhotoUID photoUID = res.PhotoUID
// Add photo to album if a list of albums was provided when importing. // Add photo to album if a list of albums was provided when importing.
if err := entity.AddPhotoToAlbums(photoUID, impOpt.Albums); err != nil { if err := entity.AddPhotoToAlbums(photoUID, opt.Albums); err != nil {
log.Warn(err) log.Warn(err)
} }
} }

View File

@@ -14,7 +14,9 @@ import (
func TestImportWorker_OriginalFileNames(t *testing.T) { func TestImportWorker_OriginalFileNames(t *testing.T) {
conf := config.TestConfig() conf := config.TestConfig()
conf.InitializeTestData() if err := conf.InitializeTestData(); err != nil {
t.Fatal(err)
}
tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow()) tf := classify.New(conf.AssetsPath(), conf.DisableTensorFlow())
nd := nsfw.New(conf.NSFWModelPath()) nd := nsfw.New(conf.NSFWModelPath())
@@ -55,7 +57,7 @@ func TestImportWorker_OriginalFileNames(t *testing.T) {
FileName: mediaFile.FileName(), FileName: mediaFile.FileName(),
Related: relatedFiles, Related: relatedFiles,
IndexOpt: IndexOptionsAll(), IndexOpt: IndexOptionsAll(),
ImportOpt: ImportOptionsCopy(conf.ImportPath()), ImportOpt: ImportOptionsCopy(conf.ImportPath(), conf.ImportDest()),
Imp: imp, Imp: imp,
} }

View File

@@ -39,7 +39,7 @@ type Index struct {
// NewIndex returns a new indexer and expects its dependencies as arguments. // NewIndex returns a new indexer and expects its dependencies as arguments.
func NewIndex(conf *config.Config, tensorFlow *classify.TensorFlow, nsfwDetector *nsfw.Detector, faceNet *face.Net, convert *Convert, files *Files, photos *Photos) *Index { func NewIndex(conf *config.Config, tensorFlow *classify.TensorFlow, nsfwDetector *nsfw.Detector, faceNet *face.Net, convert *Convert, files *Files, photos *Photos) *Index {
if conf == nil { if conf == nil {
log.Errorf("index: config is nil") log.Errorf("index: config is not set")
return nil return nil
} }
@@ -82,7 +82,7 @@ func (ind *Index) Start(o IndexOptions) fs.Done {
done := make(fs.Done) done := make(fs.Done)
if ind.conf == nil { if ind.conf == nil {
log.Errorf("index: config is nil") log.Errorf("index: config is not set")
return done return done
} }

View File

@@ -1,6 +1,6 @@
package photoprism package photoprism
// IndexOptions represents media file indexing options. // IndexOptions represents file indexing options.
type IndexOptions struct { type IndexOptions struct {
Path string Path string
Rescan bool Rescan bool

View File

@@ -28,7 +28,7 @@ func TestIndex_Start(t *testing.T) {
ind := NewIndex(conf, tf, nd, fn, convert, NewFiles(), NewPhotos()) ind := NewIndex(conf, tf, nd, fn, convert, NewFiles(), NewPhotos())
imp := NewImport(conf, ind, convert) imp := NewImport(conf, ind, convert)
opt := ImportOptionsMove(conf.ImportPath()) opt := ImportOptionsMove(conf.ImportPath(), "")
imp.Start(opt) imp.Start(opt)

View File

@@ -38,7 +38,7 @@ func TestResample_Start(t *testing.T) {
ind := NewIndex(conf, tf, nd, fn, convert, NewFiles(), NewPhotos()) ind := NewIndex(conf, tf, nd, fn, convert, NewFiles(), NewPhotos())
imp := NewImport(conf, ind, convert) imp := NewImport(conf, ind, convert)
opt := ImportOptionsMove(conf.ImportPath()) opt := ImportOptionsMove(conf.ImportPath(), "")
imp.Start(opt) imp.Start(opt)

15
internal/search/errors.go Normal file
View File

@@ -0,0 +1,15 @@
package search
import (
"fmt"
"github.com/photoprism/photoprism/internal/i18n"
)
var (
ErrForbidden = i18n.Error(i18n.ErrForbidden)
ErrBadRequest = i18n.Error(i18n.ErrBadRequest)
ErrBadSortOrder = fmt.Errorf("iinvalid sort order")
ErrBadFilter = fmt.Errorf("search filter is invalid")
ErrInvalidId = fmt.Errorf("invalid ID specified")
)

View File

@@ -9,9 +9,10 @@ import (
"github.com/dustin/go-humanize/english" "github.com/dustin/go-humanize/english"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/internal/acl"
"github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/event"
"github.com/photoprism/photoprism/internal/form" "github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/fs" "github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/rnd" "github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/txt" "github.com/photoprism/photoprism/pkg/txt"
@@ -28,38 +29,46 @@ var FileTypes = []string{fs.ImageJPEG.String(), fs.ImagePNG.String(), fs.ImageGI
// Photos finds photos based on the search form provided and returns them as PhotoResults. // Photos finds photos based on the search form provided and returns them as PhotoResults.
func Photos(f form.SearchPhotos) (results PhotoResults, count int, err error) { func Photos(f form.SearchPhotos) (results PhotoResults, count int, err error) {
return searchPhotos(f, PhotosColsAll) return searchPhotos(f, nil, PhotosColsAll)
}
// UserPhotos finds photos based on the search form and user session then returns them as PhotoResults.
func UserPhotos(f form.SearchPhotos, sess *entity.Session) (results PhotoResults, count int, err error) {
return searchPhotos(f, sess, PhotosColsAll)
} }
// PhotoIds finds photo and file ids based on the search form provided and returns them as PhotoResults. // PhotoIds finds photo and file ids based on the search form provided and returns them as PhotoResults.
func PhotoIds(f form.SearchPhotos) (files PhotoResults, count int, err error) { func PhotoIds(f form.SearchPhotos) (files PhotoResults, count int, err error) {
f.Merged = false f.Merged = false
f.Primary = true f.Primary = true
return searchPhotos(f, "photos.id, photos.photo_uid, files.file_uid") return searchPhotos(f, nil, "photos.id, photos.photo_uid, files.file_uid")
} }
// photos searches for photos based on a Form and returns PhotoResults ([]Photo). // searchPhotos finds photos based on the search form and user session then returns them as PhotoResults.
func searchPhotos(f form.SearchPhotos, resultCols string) (results PhotoResults, count int, err error) { func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string) (results PhotoResults, count int, err error) {
start := time.Now() start := time.Now()
s := UnscopedDb() // Parse query string and filter.
// s = s.LogMode(true) if err = f.ParseQueryString(); err != nil {
log.Debugf("search: %s", err)
return PhotoResults{}, 0, ErrBadRequest
}
// Database tables. // Specify table names and joins.
s = s.Table("files").Select(resultCols). s := UnscopedDb().Table(entity.File{}.TableName()).Select(resultCols).
Joins("JOIN photos ON files.photo_id = photos.id AND files.media_id IS NOT NULL"). Joins("JOIN photos ON files.photo_id = photos.id AND files.media_id IS NOT NULL").
Joins("LEFT JOIN cameras ON photos.camera_id = cameras.id"). Joins("LEFT JOIN cameras ON photos.camera_id = cameras.id").
Joins("LEFT JOIN lenses ON photos.lens_id = lenses.id"). Joins("LEFT JOIN lenses ON photos.lens_id = lenses.id").
Joins("LEFT JOIN places ON photos.place_id = places.id") Joins("LEFT JOIN places ON photos.place_id = places.id")
// Offset and count. // Limit offset and count.
if f.Count > 0 && f.Count <= MaxResults { if f.Count > 0 && f.Count <= MaxResults {
s = s.Limit(f.Count).Offset(f.Offset) s = s.Limit(f.Count).Offset(f.Offset)
} else { } else {
s = s.Limit(MaxResults).Offset(f.Offset) s = s.Limit(MaxResults).Offset(f.Offset)
} }
// Sort order. // Set sort order.
switch f.Order { switch f.Order {
case entity.SortOrderEdited: case entity.SortOrderEdited:
s = s.Where("photos.edited_at IS NOT NULL").Order("photos.edited_at DESC, files.media_id") s = s.Where("photos.edited_at IS NOT NULL").Order("photos.edited_at DESC, files.media_id")
@@ -81,7 +90,61 @@ func searchPhotos(f form.SearchPhotos, resultCols string) (results PhotoResults,
case entity.SortOrderDefault, entity.SortOrderImported, entity.SortOrderAdded: case entity.SortOrderDefault, entity.SortOrderImported, entity.SortOrderAdded:
s = s.Order("files.media_id") s = s.Order("files.media_id")
default: default:
return PhotoResults{}, 0, fmt.Errorf("invalid sort order") return PhotoResults{}, 0, ErrBadSortOrder
}
// Limit search results to a specific UID scope, e.g. when sharing.
if txt.NotEmpty(f.In) {
f.In = strings.ToLower(f.In)
if idType, idPrefix := rnd.IdType(f.In); idType != rnd.TypeUID || idPrefix != entity.AlbumUID {
return PhotoResults{}, 0, ErrInvalidId
} else if a, err := entity.CachedAlbumByUID(f.In); err != nil || a.AlbumUID == "" {
return PhotoResults{}, 0, ErrInvalidId
} else if a.AlbumFilter == "" {
s = s.Joins("JOIN photos_albums ON photos_albums.photo_uid = files.photo_uid").
Where("photos_albums.hidden = 0 AND photos_albums.album_uid = ?", a.AlbumUID)
} else if err = form.Unserialize(&f, a.AlbumFilter); err != nil {
return PhotoResults{}, 0, ErrBadFilter
} else {
f.Filter = a.AlbumFilter
s = s.Where("files.photo_uid NOT IN (SELECT photo_uid FROM photos_albums pa WHERE pa.hidden = 1 AND pa.album_uid = ?)", a.AlbumUID)
}
} else {
f.In = ""
}
// Check session permissions and apply as needed.
if sess != nil {
aclRole := sess.User().AclRole()
// Visitors and other restricted users can only access shared content.
if !sess.HasShare(f.In) && (sess.IsVisitor() || sess.Unregistered()) ||
f.In == "" && acl.Resources.Deny(acl.ResourcePhotos, aclRole, acl.ActionSearch) {
event.AuditErr([]string{sess.IP(), "session %s", "%s %s as %s", "denied"}, sess.RefID, acl.ActionSearch.String(), string(acl.ResourcePhotos), aclRole)
return PhotoResults{}, 0, ErrForbidden
}
// Exclude private content?
if acl.Resources.Deny(acl.ResourcePhotos, aclRole, acl.AccessPrivate) {
f.Public = true
f.Private = false
}
// Exclude archived content?
if acl.Resources.Deny(acl.ResourcePhotos, aclRole, acl.ActionDelete) {
f.Archived = false
f.Review = false
}
// Exclude hidden files?
if acl.Resources.Deny(acl.ResourceFiles, aclRole, acl.AccessAll) {
f.Hidden = false
}
// Restrict the search to a sub-folder, if specified.
if dir := sess.User().BasePath; f.In == "" && dir != "" {
s = s.Where("photos.photo_path LIKE ?", dir+"%")
}
} }
// Limit the result file types if hidden images/videos should not be found. // Limit the result file types if hidden images/videos should not be found.
@@ -102,10 +165,27 @@ func searchPhotos(f form.SearchPhotos, resultCols string) (results PhotoResults,
// Find only certain unique IDs? // Find only certain unique IDs?
if txt.NotEmpty(f.UID) { if txt.NotEmpty(f.UID) {
s = s.Where("photos.photo_uid IN (?)", SplitOr(strings.ToLower(f.UID))) ids := SplitOr(strings.ToLower(f.UID))
// Take shortcut? if idType, prefix := rnd.ContainsType(ids); idType == rnd.TypeUID {
if f.Album == "" && f.Query == "" { switch prefix {
case entity.PhotoUID:
s = s.Where("photos.photo_uid IN (?)", ids)
case entity.FileUID:
s = s.Where("files.file_uid IN (?)", ids)
default:
log.Debugf("(1) idType: %s, prefix: %s", idType, prefix)
return PhotoResults{}, 0, fmt.Errorf("invalid %s specified", idType)
}
} else if idType.SHA() {
s = s.Where("files.file_hash IN (?)", ids)
} else {
log.Debugf("(2) idType: %s, prefix: %s", idType, prefix)
return PhotoResults{}, 0, ErrInvalidId
}
// Find UIDs only to improve performance?
if sess == nil && f.FindUidOnly() {
s = s.Order("files.media_id") s = s.Order("files.media_id")
if result := s.Scan(&results); result.Error != nil { if result := s.Scan(&results); result.Error != nil {
@@ -120,13 +200,14 @@ func searchPhotos(f form.SearchPhotos, resultCols string) (results PhotoResults,
return results, len(results), nil return results, len(results), nil
} }
} else {
f.UID = ""
} }
// Filter by label, label category and keywords. // Filter by label, label category and keywords.
var categories []entity.Category var categories []entity.Category
var labels []entity.Label var labels []entity.Label
var labelIds []uint var labelIds []uint
if txt.NotEmpty(f.Label) { if txt.NotEmpty(f.Label) {
if err := Db().Where(AnySlug("label_slug", f.Label, txt.Or)).Or(AnySlug("custom_slug", f.Label, txt.Or)).Find(&labels).Error; len(labels) == 0 || err != nil { if err := Db().Where(AnySlug("label_slug", f.Label, txt.Or)).Or(AnySlug("custom_slug", f.Label, txt.Or)).Find(&labels).Error; len(labels) == 0 || err != nil {
log.Debugf("search: label %s not found", txt.LogParamLower(f.Label)) log.Debugf("search: label %s not found", txt.LogParamLower(f.Label))
@@ -550,15 +631,20 @@ func searchPhotos(f form.SearchPhotos, resultCols string) (results PhotoResults,
} }
} }
if err := s.Scan(&results).Error; err != nil { // Query database.
if err = s.Scan(&results).Error; err != nil {
return results, 0, err return results, 0, err
} }
// Log number of results.
log.Debugf("photos: found %s for %s [%s]", english.Plural(len(results), "result", "results"), f.SerializeAll(), time.Since(start)) log.Debugf("photos: found %s for %s [%s]", english.Plural(len(results), "result", "results"), f.SerializeAll(), time.Since(start))
// Merge files that belong to the same photo?
if f.Merged { if f.Merged {
// Return merged files.
return results.Merge() return results.Merge()
} }
// Return unmerged files.
return results, len(results), nil return results, len(results), nil
} }

View File

@@ -14,11 +14,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Berlin*" f.Album = "Berlin*"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -32,11 +27,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Pet*" f.Album = "Pet*"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -50,11 +40,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "%gold" f.Album = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -69,11 +54,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "I love % dog" f.Album = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -89,11 +69,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "sale%" f.Album = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -108,11 +83,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "&IlikeFood" f.Album = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -127,11 +97,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Pets & Dogs" f.Album = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -145,11 +110,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Light&" f.Album = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -163,11 +123,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "'Family" f.Album = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -181,11 +136,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Father's Day" f.Album = "Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -199,11 +149,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Ice Cream'" f.Album = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -217,11 +162,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "*Forrest" f.Album = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -235,11 +175,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "My*Kids" f.Album = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -253,11 +188,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Yoga***" f.Album = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -271,11 +201,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "|Banana" f.Album = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -290,11 +215,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Red|Green" f.Album = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -309,11 +229,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Blue|" f.Album = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -327,11 +242,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "345 Shirt" f.Album = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -345,11 +255,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Color555 Blue" f.Album = "Color555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -363,11 +268,6 @@ func TestPhotosFilterAlbum(t *testing.T) {
f.Album = "Route 66" f.Album = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -384,11 +284,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Berlin*\"" f.Query = "album:\"Berlin*\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -402,11 +297,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Pet*\"" f.Query = "album:\"Pet*\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -420,11 +310,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"%gold\"" f.Query = "album:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -438,11 +323,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"I love % dog\"" f.Query = "album:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -456,11 +336,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"sale%\"" f.Query = "album:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -474,11 +349,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"&IlikeFood\"" f.Query = "album:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -493,11 +363,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Pets & Dogs\"" f.Query = "album:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -511,11 +376,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Light&\"" f.Query = "album:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -529,11 +389,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"'Family\"" f.Query = "album:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -547,11 +402,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Father's Day\"" f.Query = "album:\"Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -565,11 +415,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Ice Cream'\"" f.Query = "album:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -584,11 +429,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"*Forrest\"" f.Query = "album:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -603,11 +443,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"My*Kids\"" f.Query = "album:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -622,11 +457,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Yoga***\"" f.Query = "album:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -641,11 +471,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"|Banana\"" f.Query = "album:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -660,11 +485,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Red|Green\"" f.Query = "album:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -679,11 +499,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Blue|\"" f.Query = "album:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -698,11 +513,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"345 Shirt\"" f.Query = "album:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -717,11 +527,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Color555 Blue\"" f.Query = "album:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -736,11 +541,6 @@ func TestPhotosQueryAlbum(t *testing.T) {
f.Query = "album:\"Route 66\"" f.Query = "album:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -15,11 +15,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Berlin 2019" f.Albums = "Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -33,11 +28,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet*" f.Albums = "Pet*"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -51,11 +41,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet*|Berlin 2019" f.Albums = "Pet*|Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -69,11 +54,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet* | Berlin 2019" f.Albums = "Pet* | Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -87,11 +67,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet* or Berlin 2019" f.Albums = "Pet* or Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -105,11 +80,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet* OR Berlin 2019" f.Albums = "Pet* OR Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -123,11 +93,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet*&Berlin 2019" f.Albums = "Pet*&Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -141,11 +106,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet* & Berlin 2019" f.Albums = "Pet* & Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -159,11 +119,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet* and Berlin 2019" f.Albums = "Pet* and Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -177,11 +132,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pet* AND Berlin 2019" f.Albums = "Pet* AND Berlin 2019"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -195,11 +145,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "%gold" f.Albums = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -213,11 +158,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "I love % dog" f.Albums = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -231,11 +171,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "sale%" f.Albums = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -249,11 +184,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "&IlikeFood" f.Albums = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -267,11 +197,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Pets & Dogs" f.Albums = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -285,11 +210,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Light&" f.Albums = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -303,11 +223,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "'Family" f.Albums = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -321,11 +236,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Father's Day" f.Albums = "Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -340,11 +250,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Ice Cream'" f.Albums = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -358,11 +263,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "*Forrest" f.Albums = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -376,11 +276,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "My*Kids" f.Albums = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -394,11 +289,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Yoga***" f.Albums = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -412,11 +302,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "|Banana" f.Albums = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -430,11 +315,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Red|Green" f.Albums = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, count, err := Photos(f) photos, count, err := Photos(f)
if err != nil { if err != nil {
@@ -454,11 +334,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Blue|" f.Albums = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -473,11 +348,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "345 Shirt" f.Albums = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -491,11 +361,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Color555 Blue" f.Albums = "Color555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -509,11 +374,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Route 66" f.Albums = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -527,11 +387,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Route 66 & Father's Day" f.Albums = "Route 66 & Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -545,11 +400,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Route 66 | Father's Day" f.Albums = "Route 66 | Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -563,11 +413,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Red|Green & Father's Day" f.Albums = "Red|Green & Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -581,11 +426,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Red|Green | Father's Day" f.Albums = "Red|Green | Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -599,11 +439,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Light& & Red|Green" f.Albums = "Light& & Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -617,11 +452,6 @@ func TestPhotosFilterAlbums(t *testing.T) {
f.Albums = "Red|Green | Light&" f.Albums = "Red|Green | Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -638,11 +468,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Berlin 2019\"" f.Query = "albums:\"Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -656,11 +481,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet*\"" f.Query = "albums:\"Pet*\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -674,11 +494,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet*|Berlin 2019\"" f.Query = "albums:\"Pet*|Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -692,11 +507,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet* | Berlin 2019\"" f.Query = "albums:\"Pet* | Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -710,11 +520,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet* or Berlin 2019\"" f.Query = "albums:\"Pet* or Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -728,11 +533,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet* OR Berlin 2019\"" f.Query = "albums:\"Pet* OR Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -746,11 +546,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet*&Berlin 2019\"" f.Query = "albums:\"Pet*&Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -764,11 +559,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet* & Berlin 2019\"" f.Query = "albums:\"Pet* & Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -782,11 +572,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet* and Berlin 2019\"" f.Query = "albums:\"Pet* and Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -800,11 +585,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pet* AND Berlin 2019\"" f.Query = "albums:\"Pet* AND Berlin 2019\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -818,11 +598,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"%gold\"" f.Query = "albums:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -836,11 +611,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"I love % dog\"" f.Query = "albums:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -854,11 +624,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"sale%\"" f.Query = "albums:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -872,11 +637,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"&IlikeFood\"" f.Query = "albums:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -890,11 +650,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Pets & Dogs\"" f.Query = "albums:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -908,11 +663,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Light&\"" f.Query = "albums:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -926,11 +676,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"'Family\"" f.Query = "albums:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -944,11 +689,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Father's Day\"" f.Query = "albums:\"Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -963,11 +703,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Ice Cream'\"" f.Query = "albums:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -981,11 +716,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"*Forrest\"" f.Query = "albums:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -999,11 +729,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"My*Kids\"" f.Query = "albums:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1017,11 +742,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Yoga***\"" f.Query = "albums:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1035,11 +755,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"|Banana\"" f.Query = "albums:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1053,11 +768,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Red|Green\"" f.Query = "albums:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, count, err := Photos(f) photos, count, err := Photos(f)
if err != nil { if err != nil {
@@ -1077,11 +787,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Blue|\"" f.Query = "albums:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1095,11 +800,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"345 Shirt\"" f.Query = "albums:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1113,11 +813,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Color555 Blue\"" f.Query = "albums:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1131,11 +826,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Route 66\"" f.Query = "albums:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1149,11 +839,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Route 66 & Father's Day\"" f.Query = "albums:\"Route 66 & Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1167,11 +852,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Route 66 | Father's Day\"" f.Query = "albums:\"Route 66 | Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1185,11 +865,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Red|Green & Father's Day\"" f.Query = "albums:\"Red|Green & Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1203,11 +878,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Red|Green | Father's Day\"" f.Query = "albums:\"Red|Green | Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1221,11 +891,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Light& & Red|Green\"" f.Query = "albums:\"Light& & Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -1239,11 +904,6 @@ func TestPhotosQueryAlbums(t *testing.T) {
f.Query = "albums:\"Red|Green | Light&\"" f.Query = "albums:\"Red|Green | Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -31,11 +31,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:yes" f.Query = "animated:yes"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -49,11 +44,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:yes" f.Query = "animated:yes"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -63,11 +53,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:false" f.Query = "animated:false"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos2, _, err2 := Photos(f) photos2, _, err2 := Photos(f)
if err2 != nil { if err2 != nil {
@@ -81,11 +66,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"%gold\"" f.Query = "animated:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -99,11 +79,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"I love % dog\"" f.Query = "animated:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -117,11 +92,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"sale%\"" f.Query = "animated:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -135,11 +105,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"&IlikeFood\"" f.Query = "animated:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -154,11 +119,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Pets & Dogs\"" f.Query = "animated:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -172,11 +132,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Light&\"" f.Query = "animated:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -191,11 +146,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"'Family\"" f.Query = "animated:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -209,11 +159,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Mother's Day\"" f.Query = "animated:\"Mother's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -228,11 +173,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Ice Cream'\"" f.Query = "animated:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -247,11 +187,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"*Forrest\"" f.Query = "animated:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -266,11 +201,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"My*Kids\"" f.Query = "animated:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -285,11 +215,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Yoga***\"" f.Query = "animated:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -304,11 +229,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"|Banana\"" f.Query = "animated:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -323,11 +243,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Red|Green\"" f.Query = "animated:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -342,11 +257,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Blue|\"" f.Query = "animated:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -361,11 +271,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"345 Shirt\"" f.Query = "animated:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -380,11 +285,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Color555 Blue\"" f.Query = "animated:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -399,11 +299,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Route 66\"" f.Query = "animated:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -418,11 +313,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Route 66 & Father's Day\"" f.Query = "animated:\"Route 66 & Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -437,11 +327,6 @@ func TestPhotosQueryAnimated(t *testing.T) {
f.Query = "animated:\"Route %66 | *Father's Day\"" f.Query = "animated:\"Route %66 | *Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -31,11 +31,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:yes" f.Query = "archived:yes"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -45,11 +40,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:false" f.Query = "archived:false"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos2, _, err2 := Photos(f) photos2, _, err2 := Photos(f)
if err2 != nil { if err2 != nil {
@@ -63,11 +53,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"%gold\"" f.Query = "archived:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -81,11 +66,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"I love % dog\"" f.Query = "archived:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -99,11 +79,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"sale%\"" f.Query = "archived:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -117,11 +92,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"&IlikeFood\"" f.Query = "archived:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -136,11 +106,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Pets & Dogs\"" f.Query = "archived:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -154,11 +119,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Light&\"" f.Query = "archived:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -173,11 +133,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"'Family\"" f.Query = "archived:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -192,11 +147,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Mother's Day\"" f.Query = "archived:\"Mother's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -211,11 +161,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Ice Cream'\"" f.Query = "archived:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -230,11 +175,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"*Forrest\"" f.Query = "archived:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -249,11 +189,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"My*Kids\"" f.Query = "archived:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -268,11 +203,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Yoga***\"" f.Query = "archived:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -287,11 +217,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"|Banana\"" f.Query = "archived:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -306,11 +231,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Red|Green\"" f.Query = "archived:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -325,11 +245,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Blue|\"" f.Query = "archived:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -344,11 +259,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"345 Shirt\"" f.Query = "archived:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -363,11 +273,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Color555 Blue\"" f.Query = "archived:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -382,11 +287,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Route 66\"" f.Query = "archived:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -401,11 +301,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Route 66 & Father's Day\"" f.Query = "archived:\"Route 66 & Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -420,11 +315,6 @@ func TestPhotosQueryArchived(t *testing.T) {
f.Query = "archived:\"Route %66 | *Father's Day\"" f.Query = "archived:\"Route %66 | *Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -15,11 +15,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Apple iPhone SE" f.Camera = "Apple iPhone SE"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -33,11 +28,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Apple" f.Camera = "Apple"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -51,11 +41,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "%gold" f.Camera = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -69,11 +54,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "I love % dog" f.Camera = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -87,11 +67,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "sale%" f.Camera = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -105,11 +80,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "&IlikeFood" f.Camera = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -123,11 +93,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Pets & Dogs" f.Camera = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -141,11 +106,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Light&" f.Camera = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -159,11 +119,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "'Family" f.Camera = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -177,11 +132,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Father's camera" f.Camera = "Father's camera"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -196,11 +146,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Ice Cream'" f.Camera = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -214,11 +159,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "*Forrest" f.Camera = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -232,11 +172,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "My*Kids" f.Camera = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -250,11 +185,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Yoga***" f.Camera = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -268,11 +198,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "|Banana" f.Camera = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -286,11 +211,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Red|Green" f.Camera = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -305,11 +225,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Blue|" f.Camera = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -324,11 +239,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "345 Shirt" f.Camera = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -342,11 +252,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "camera555 Blue" f.Camera = "camera555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -360,11 +265,6 @@ func TestPhotosFilterCamera(t *testing.T) {
f.Camera = "Route 66" f.Camera = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -381,11 +281,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Apple iPhone SE\"" f.Query = "camera:\"Apple iPhone SE\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -399,11 +294,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Apple\"" f.Query = "camera:\"Apple\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -417,11 +307,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"%gold\"" f.Query = "camera:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -435,11 +320,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"I love % dog\"" f.Query = "camera:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -453,11 +333,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"sale%\"" f.Query = "camera:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -471,11 +346,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"&IlikeFood\"" f.Query = "camera:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -489,11 +359,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Pets & Dogs\"" f.Query = "camera:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -507,11 +372,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Light&\"" f.Query = "camera:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -525,11 +385,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"'Family\"" f.Query = "camera:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -543,11 +398,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Father's camera\"" f.Query = "camera:\"Father's camera\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -562,11 +412,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Ice Cream'\"" f.Query = "camera:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -580,11 +425,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"*Forrest\"" f.Query = "camera:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -598,11 +438,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"My*Kids\"" f.Query = "camera:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -616,11 +451,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Yoga***\"" f.Query = "camera:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -634,11 +464,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"|Banana\"" f.Query = "camera:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -652,11 +477,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Red|Green\"" f.Query = "camera:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -671,11 +491,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Blue|\"" f.Query = "camera:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -689,11 +504,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"345 Shirt\"" f.Query = "camera:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -707,11 +517,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"camera555 Blue\"" f.Query = "camera:\"camera555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -725,11 +530,6 @@ func TestPhotosQueryCamera(t *testing.T) {
f.Query = "camera:\"Route 66\"" f.Query = "camera:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -15,11 +15,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "%gold" f.Category = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -33,11 +28,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "I love % dog" f.Category = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -51,11 +41,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "sale%" f.Category = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -69,11 +54,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "&IlikeFood" f.Category = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -87,11 +67,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Pets & Dogs" f.Category = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -105,11 +80,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Light&" f.Category = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -123,11 +93,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "'Family" f.Category = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -141,11 +106,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Father's category" f.Category = "Father's category"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -160,11 +120,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Ice Cream'" f.Category = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -178,11 +133,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "*Forrest" f.Category = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -196,11 +146,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "My*Camping" f.Category = "My*Camping"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -214,11 +159,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Camping***" f.Category = "Camping***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -232,11 +172,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "|Camping" f.Category = "|Camping"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -250,11 +185,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Camping|botanical garden" f.Category = "Camping|botanical garden"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -271,11 +201,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Camping|" f.Category = "Camping|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -289,11 +214,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "345 Shirt" f.Category = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -307,11 +227,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "category555 Blue" f.Category = "category555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -325,11 +240,6 @@ func TestPhotosFilterCategory(t *testing.T) {
f.Category = "Route 66" f.Category = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -346,11 +256,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"%gold\"" f.Query = "category:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -364,11 +269,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"I love % dog\"" f.Query = "category:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -382,11 +282,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"sale%\"" f.Query = "category:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -400,11 +295,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"&IlikeFood\"" f.Query = "category:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -418,11 +308,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Pets & Dogs\"" f.Query = "category:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -436,11 +321,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Light&\"" f.Query = "category:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -454,11 +334,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"'Family\"" f.Query = "category:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -472,11 +347,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Father's category\"" f.Query = "category:\"Father's category\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -491,11 +361,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Ice Cream'\"" f.Query = "category:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -509,11 +374,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"*Forrest\"" f.Query = "category:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -527,11 +387,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"My*Kids\"" f.Query = "category:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -545,11 +400,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Yoga***\"" f.Query = "category:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -563,11 +413,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"|Banana\"" f.Query = "category:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -581,11 +426,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Red|Green\"" f.Query = "category:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -600,11 +440,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Blue|\"" f.Query = "category:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -618,11 +453,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"345 Shirt\"" f.Query = "category:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -636,11 +466,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"category555 Blue\"" f.Query = "category:\"category555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -654,11 +479,6 @@ func TestPhotosQueryCategory(t *testing.T) {
f.Query = "category:\"Route 66\"" f.Query = "category:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -15,11 +15,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Teotihuacán" f.City = "Teotihuacán"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -33,11 +28,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Neustadt*" f.City = "Neustadt*"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -52,11 +42,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Teotihuacán|Neustadt an der Weinstraße" f.City = "Teotihuacán|Neustadt an der Weinstraße"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -70,11 +55,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Teotihuacán | Neustadt an der Weinstraße" f.City = "Teotihuacán | Neustadt an der Weinstraße"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -88,11 +68,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Teotihuacán or Neustadt an der Weinstraße" f.City = "Teotihuacán or Neustadt an der Weinstraße"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -106,11 +81,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Teotihuacán OR Neustadt an der Weinstraße" f.City = "Teotihuacán OR Neustadt an der Weinstraße"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -124,11 +94,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "%gold" f.City = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -142,11 +107,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "I love % dog" f.City = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -160,11 +120,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "sale%" f.City = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -178,11 +133,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "&IlikeFood" f.City = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -196,11 +146,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Pets & Dogs" f.City = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -214,11 +159,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Light&" f.City = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -232,11 +172,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "'Family" f.City = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -250,11 +185,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Father's state" f.City = "Father's state"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -269,11 +199,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Ice Cream'" f.City = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -287,11 +212,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "*Forrest" f.City = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -305,11 +225,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "My*Kids" f.City = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -323,11 +238,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Yoga***" f.City = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -341,11 +251,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "|New york" f.City = "|New york"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -360,11 +265,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Red|Green" f.City = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -379,11 +279,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Neustadt an der Weinstraße|" f.City = "Neustadt an der Weinstraße|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -397,11 +292,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "345 Shirt" f.City = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -415,11 +305,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "state555 Blue" f.City = "state555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -433,11 +318,6 @@ func TestPhotosFilterCity(t *testing.T) {
f.City = "Route 66" f.City = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -454,11 +334,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Teotihuacán\"" f.Query = "city:\"Teotihuacán\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -472,11 +347,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Neustadt*\"" f.Query = "city:\"Neustadt*\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -490,11 +360,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Teotihuacán|Neustadt an der Weinstraße\"" f.Query = "city:\"Teotihuacán|Neustadt an der Weinstraße\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -508,11 +373,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Teotihuacán | Neustadt an der Weinstraße\"" f.Query = "city:\"Teotihuacán | Neustadt an der Weinstraße\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -526,11 +386,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Teotihuacán or Neustadt an der Weinstraße\"" f.Query = "city:\"Teotihuacán or Neustadt an der Weinstraße\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -544,11 +399,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Teotihuacán OR Neustadt an der Weinstraße\"" f.Query = "city:\"Teotihuacán OR Neustadt an der Weinstraße\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -562,11 +412,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"%gold\"" f.Query = "city:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -580,11 +425,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"I love % dog\"" f.Query = "city:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -598,11 +438,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"sale%\"" f.Query = "city:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -616,11 +451,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"&IlikeFood\"" f.Query = "city:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -634,11 +464,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Pets & Dogs\"" f.Query = "city:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -652,11 +477,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Light&\"" f.Query = "city:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -670,11 +490,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"'Family\"" f.Query = "city:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -688,11 +503,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Father's state\"" f.Query = "city:\"Father's state\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -707,11 +517,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Ice Cream'\"" f.Query = "city:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -725,11 +530,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"*Forrest\"" f.Query = "city:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -743,11 +543,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"My*Kids\"" f.Query = "city:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -761,11 +556,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Yoga***\"" f.Query = "city:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -779,11 +569,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"|Banana\"" f.Query = "city:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -797,11 +582,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Red|Green\"" f.Query = "city:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -816,11 +596,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Neustadt an der Weinstraße|\"" f.Query = "city:\"Neustadt an der Weinstraße|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -834,11 +609,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"345 Shirt\"" f.Query = "city:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -852,11 +622,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"state555 Blue\"" f.Query = "city:\"state555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -870,11 +635,6 @@ func TestPhotosQueryCity(t *testing.T) {
f.Query = "city:\"Route 66\"" f.Query = "city:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -29,11 +29,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "%gold" f.Color = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -47,11 +42,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "I love % dog" f.Color = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -65,11 +55,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "sale%" f.Color = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -83,11 +68,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "&IlikeFood" f.Color = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -101,11 +81,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Pets & Dogs" f.Color = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -119,11 +94,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Light&" f.Color = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -137,11 +107,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "'Family" f.Color = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -155,11 +120,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Father's Day" f.Color = "Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -174,11 +134,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Ice Cream'" f.Color = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -192,11 +147,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "*Forrest" f.Color = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -210,11 +160,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "My*Kids" f.Color = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -228,11 +173,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Yoga***" f.Color = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -246,11 +186,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "|Banana" f.Color = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -264,11 +199,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Red|Green" f.Color = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -283,11 +213,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Blue|" f.Color = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -302,11 +227,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "345 Shirt" f.Color = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -320,11 +240,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Color555 Blue" f.Color = "Color555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -338,11 +253,6 @@ func TestPhotosFilterColor(t *testing.T) {
f.Color = "Route 66" f.Color = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -373,11 +283,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"%gold\"" f.Query = "color:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -391,11 +296,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"I love % dog\"" f.Query = "color:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -409,11 +309,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"sale%\"" f.Query = "color:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -427,11 +322,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"&IlikeFood\"" f.Query = "color:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -445,11 +335,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Pets & Dogs\"" f.Query = "color:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -463,11 +348,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Light&\"" f.Query = "color:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -481,11 +361,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"'Family\"" f.Query = "color:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -499,11 +374,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Father's Day\"" f.Query = "color:\"Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -518,11 +388,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Ice Cream'\"" f.Query = "color:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -536,11 +401,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"*Forrest\"" f.Query = "color:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -554,11 +414,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"My*Kids\"" f.Query = "color:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -572,11 +427,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Yoga***\"" f.Query = "color:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -590,11 +440,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"|Banana\"" f.Query = "color:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -608,11 +453,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Red|Green\"" f.Query = "color:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -627,11 +467,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Blue|\"" f.Query = "color:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -645,11 +480,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"345 Shirt\"" f.Query = "color:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -663,11 +493,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Color555 Blue\"" f.Query = "color:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -681,11 +506,6 @@ func TestPhotosQueryColor(t *testing.T) {
f.Query = "color:\"Route 66\"" f.Query = "color:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -15,11 +15,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "de" f.Country = "de"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -33,11 +28,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "mx" f.Country = "mx"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -51,11 +41,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "mx|de" f.Country = "mx|de"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -69,11 +54,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "mx | de" f.Country = "mx | de"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -87,11 +67,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "%gold" f.Country = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -105,11 +80,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "I love % dog" f.Country = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -123,11 +93,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "sale%" f.Country = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -141,11 +106,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "&IlikeFood" f.Country = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -159,11 +119,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Pets & Dogs" f.Country = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -177,11 +132,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Light&" f.Country = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -195,11 +145,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "'Family" f.Country = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -213,11 +158,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Father's country" f.Country = "Father's country"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -232,11 +172,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Ice Cream'" f.Country = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -250,11 +185,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "*Forrest" f.Country = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -268,11 +198,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "My*Kids" f.Country = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -286,11 +211,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Yoga***" f.Country = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -304,11 +224,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "|Banana" f.Country = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -322,11 +237,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Red|Green" f.Country = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -341,11 +251,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Blue|" f.Country = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -360,11 +265,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "345 Shirt" f.Country = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -378,11 +278,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "country555 Blue" f.Country = "country555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -396,11 +291,6 @@ func TestPhotosFilterCountry(t *testing.T) {
f.Country = "Route 66" f.Country = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -417,11 +307,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"de\"" f.Query = "country:\"de\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -435,11 +320,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"mx\"" f.Query = "country:\"mx\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -453,11 +333,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"mx|de\"" f.Query = "country:\"mx|de\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -471,11 +346,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"mx | de\"" f.Query = "country:\"mx | de\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -490,11 +360,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"mx or de\"" f.Query = "country:\"mx or de\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -508,11 +373,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"mx OR de\"" f.Query = "country:\"mx OR de\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -526,11 +386,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"%gold\"" f.Query = "country:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -544,11 +399,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"I love % dog\"" f.Query = "country:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -562,11 +412,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"sale%\"" f.Query = "country:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -580,11 +425,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"&IlikeFood\"" f.Query = "country:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -598,11 +438,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Pets & Dogs\"" f.Query = "country:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -616,11 +451,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Light&\"" f.Query = "country:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -634,11 +464,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"'Family\"" f.Query = "country:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -652,11 +477,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Father's country\"" f.Query = "country:\"Father's country\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -671,11 +491,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Ice Cream'\"" f.Query = "country:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -689,11 +504,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"*Forrest\"" f.Query = "country:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -707,11 +517,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"My*Kids\"" f.Query = "country:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -725,11 +530,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Yoga***\"" f.Query = "country:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -743,11 +543,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"|Banana\"" f.Query = "country:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -761,11 +556,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Red|Green\"" f.Query = "country:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -780,11 +570,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Blue|\"" f.Query = "country:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -798,11 +583,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"345 Shirt\"" f.Query = "country:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -816,11 +596,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"country555 Blue\"" f.Query = "country:\"country555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -834,11 +609,6 @@ func TestPhotosQueryCountry(t *testing.T) {
f.Query = "country:\"Route 66\"" f.Query = "country:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -15,11 +15,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "1" f.Day = "1"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -33,11 +28,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "17" f.Day = "17"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -51,11 +41,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "1|17" f.Day = "1|17"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -69,11 +54,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "1 | 17" f.Day = "1 | 17"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -92,11 +72,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "%gold" f.Day = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -110,11 +85,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "I love % dog" f.Day = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -128,11 +98,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "sale%" f.Day = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -146,11 +111,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "&IlikeFood" f.Day = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -164,11 +124,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Pets & Dogs" f.Day = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -182,11 +137,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Light&" f.Day = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -200,11 +150,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "'Family" f.Day = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -218,11 +163,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Father's Day" f.Day = "Father's Day"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -237,11 +177,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Ice Cream'" f.Day = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -255,11 +190,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "*Forrest" f.Day = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -273,11 +203,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "My*Kids" f.Day = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -291,11 +216,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Yoga***" f.Day = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -309,11 +229,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "|Banana" f.Day = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -327,11 +242,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Red|Green" f.Day = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -346,11 +256,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Blue|" f.Day = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -365,11 +270,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "345 Shirt" f.Day = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -383,11 +283,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "day555 Blue" f.Day = "day555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -401,11 +296,6 @@ func TestPhotosFilterDay(t *testing.T) {
f.Day = "Route 66" f.Day = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -422,11 +312,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"1\"" f.Query = "day:\"1\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -440,11 +325,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"17\"" f.Query = "day:\"17\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -458,11 +338,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"1|17\"" f.Query = "day:\"1|17\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -476,11 +351,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"1 | 17\"" f.Query = "day:\"1 | 17\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -501,11 +371,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"%gold\"" f.Query = "day:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -519,11 +384,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"I love % dog\"" f.Query = "day:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -537,11 +397,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"sale%\"" f.Query = "day:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -555,11 +410,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"&IlikeFood\"" f.Query = "day:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -573,11 +423,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Pets & Dogs\"" f.Query = "day:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -591,11 +436,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Light&\"" f.Query = "day:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -609,11 +449,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"'Family\"" f.Query = "day:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -627,11 +462,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Father's Day\"" f.Query = "day:\"Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -646,11 +476,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Ice Cream'\"" f.Query = "day:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -664,11 +489,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"*Forrest\"" f.Query = "day:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -682,11 +502,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"My*Kids\"" f.Query = "day:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -700,11 +515,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Yoga***\"" f.Query = "day:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -718,11 +528,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"|Banana\"" f.Query = "day:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -736,11 +541,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Red|Green\"" f.Query = "day:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -755,11 +555,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Blue|\"" f.Query = "day:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -773,11 +568,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"345 Shirt\"" f.Query = "day:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -791,11 +581,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"day555 Blue\"" f.Query = "day:\"day555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -809,11 +594,6 @@ func TestPhotosQueryDay(t *testing.T) {
f.Query = "day:\"Route 66\"" f.Query = "day:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -31,11 +31,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:yes" f.Query = "error:yes"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -45,11 +40,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:false" f.Query = "error:false"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos2, _, err2 := Photos(f) photos2, _, err2 := Photos(f)
if err2 != nil { if err2 != nil {
@@ -63,11 +53,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"%gold\"" f.Query = "error:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -81,11 +66,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"I love % dog\"" f.Query = "error:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -99,11 +79,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"sale%\"" f.Query = "error:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -117,11 +92,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"&IlikeFood\"" f.Query = "error:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -136,11 +106,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Pets & Dogs\"" f.Query = "error:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -154,11 +119,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Light&\"" f.Query = "error:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -173,11 +133,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"'Family\"" f.Query = "error:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -192,11 +147,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Mother's Day\"" f.Query = "error:\"Mother's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -211,11 +161,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Ice Cream'\"" f.Query = "error:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -230,11 +175,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"*Forrest\"" f.Query = "error:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -249,11 +189,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"My*Kids\"" f.Query = "error:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -268,11 +203,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Yoga***\"" f.Query = "error:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -287,11 +217,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"|Banana\"" f.Query = "error:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -306,11 +231,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Red|Green\"" f.Query = "error:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -325,11 +245,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Blue|\"" f.Query = "error:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -344,11 +259,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"345 Shirt\"" f.Query = "error:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -363,11 +273,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Color555 Blue\"" f.Query = "error:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -382,11 +287,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Route 66\"" f.Query = "error:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -401,11 +301,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Route 66 & Father's Day\"" f.Query = "error:\"Route 66 & Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -420,11 +315,6 @@ func TestPhotosQueryError(t *testing.T) {
f.Query = "error:\"Route %66 | *Father's Day\"" f.Query = "error:\"Route %66 | *Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -20,11 +20,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "PN6QO5INYTUSAATOFL43LL2ABAV5ACZK" f.Face = "PN6QO5INYTUSAATOFL43LL2ABAV5ACZK"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -38,11 +33,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "%gold" f.Face = "%gold"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -57,11 +47,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "I love % dog" f.Face = "I love % dog"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -76,11 +61,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "sale%" f.Face = "sale%"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -94,11 +74,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "&IlikeFood" f.Face = "&IlikeFood"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -113,11 +88,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Pets & Dogs" f.Face = "Pets & Dogs"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -131,11 +101,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Light&" f.Face = "Light&"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -149,11 +114,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "'Family" f.Face = "'Family"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -168,11 +128,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Father's face" f.Face = "Father's face"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -188,11 +143,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Ice Cream'" f.Face = "Ice Cream'"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -206,11 +156,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "*Forrest" f.Face = "*Forrest"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -224,11 +169,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "My*Kids" f.Face = "My*Kids"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -243,11 +183,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Yoga***" f.Face = "Yoga***"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -261,11 +196,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "|Banana" f.Face = "|Banana"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -279,11 +209,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Red|Green" f.Face = "Red|Green"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -298,11 +223,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Blue|" f.Face = "Blue|"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -317,11 +237,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "345 Shirt" f.Face = "345 Shirt"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -336,11 +251,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "face555 Blue" f.Face = "face555 Blue"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -354,11 +264,6 @@ func TestPhotosFilterFace(t *testing.T) {
f.Face = "Route 66" f.Face = "Route 66"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -381,11 +286,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:PN6QO5INYTUSAATOFL43LL2ABAV5ACZK" f.Query = "face:PN6QO5INYTUSAATOFL43LL2ABAV5ACZK"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -399,11 +299,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"%gold\"" f.Query = "face:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -417,11 +312,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"I love % dog\"" f.Query = "face:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -436,11 +326,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"sale%\"" f.Query = "face:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -455,11 +340,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"&IlikeFood\"" f.Query = "face:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -473,11 +353,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Pets & Dogs\"" f.Query = "face:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -492,11 +367,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Light&\"" f.Query = "face:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -510,11 +380,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"'Family\"" f.Query = "face:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -528,11 +393,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Father's face\"" f.Query = "face:\"Father's face\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -548,11 +408,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Ice Cream'\"" f.Query = "face:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -568,11 +423,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"*Forrest\"" f.Query = "face:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -586,11 +436,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"My*Kids\"" f.Query = "face:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -604,11 +449,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Yoga***\"" f.Query = "face:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -624,11 +464,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"|Banana\"" f.Query = "face:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -642,11 +477,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Red|Green\"" f.Query = "face:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -661,11 +491,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Blue|\"" f.Query = "face:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -679,11 +504,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"345 Shirt\"" f.Query = "face:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -697,11 +517,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"face555 Blue\"" f.Query = "face:\"face555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -717,11 +532,6 @@ func TestPhotosQueryFace(t *testing.T) {
f.Query = "face:\"Route 66\"" f.Query = "face:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -19,11 +19,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "yes" f.Faces = "yes"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -37,11 +32,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "1" f.Faces = "1"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -55,11 +45,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "2" f.Faces = "2"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -73,11 +58,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "4" f.Faces = "4"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -91,11 +71,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "%gold" f.Faces = "%gold"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -110,11 +85,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "I love % dog" f.Faces = "I love % dog"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -129,11 +99,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "sale%" f.Faces = "sale%"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -147,11 +112,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "&IlikeFood" f.Faces = "&IlikeFood"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -166,16 +126,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Pets & Dogs" f.Faces = "Pets & Dogs"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -189,11 +139,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Light&" f.Faces = "Light&"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -207,11 +152,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "'Family" f.Faces = "'Family"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -226,11 +166,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Father's faces" f.Faces = "Father's faces"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -246,11 +181,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Ice Cream'" f.Faces = "Ice Cream'"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -264,11 +194,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "*Forrest" f.Faces = "*Forrest"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -282,11 +207,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "My*Kids" f.Faces = "My*Kids"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -301,11 +221,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Yoga***" f.Faces = "Yoga***"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -319,11 +234,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "|Banana" f.Faces = "|Banana"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -337,11 +247,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Red|Green" f.Faces = "Red|Green"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -356,11 +261,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Blue|" f.Faces = "Blue|"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -375,11 +275,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "345 Shirt" f.Faces = "345 Shirt"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -394,11 +289,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "faces555 Blue" f.Faces = "faces555 Blue"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -412,11 +302,6 @@ func TestPhotosFilterFaces(t *testing.T) {
f.Faces = "Route 66" f.Faces = "Route 66"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -439,11 +324,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:yes" f.Query = "faces:yes"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -457,11 +337,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:1" f.Query = "faces:1"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -475,11 +350,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:2" f.Query = "faces:2"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -493,11 +363,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:5" f.Query = "faces:5"
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -511,11 +376,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"%gold\"" f.Query = "faces:\"%gold\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -530,11 +390,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"I love % dog\"" f.Query = "faces:\"I love % dog\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -549,11 +404,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"sale%\"" f.Query = "faces:\"sale%\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -567,11 +417,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"&IlikeFood\"" f.Query = "faces:\"&IlikeFood\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -586,11 +431,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Pets & Dogs\"" f.Query = "faces:\"Pets & Dogs\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -604,11 +444,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Light&\"" f.Query = "faces:\"Light&\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -622,11 +457,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"'Family\"" f.Query = "faces:\"'Family\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -641,11 +471,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Father's faces\"" f.Query = "faces:\"Father's faces\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -661,11 +486,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Ice Cream'\"" f.Query = "faces:\"Ice Cream'\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -679,11 +499,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"*Forrest\"" f.Query = "faces:\"*Forrest\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -697,11 +512,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"My*Kids\"" f.Query = "faces:\"My*Kids\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -716,11 +526,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Yoga***\"" f.Query = "faces:\"Yoga***\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -734,11 +539,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"|Banana\"" f.Query = "faces:\"|Banana\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -752,11 +552,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Red|Green\"" f.Query = "faces:\"Red|Green\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -771,11 +566,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Blue|\"" f.Query = "faces:\"Blue|\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -789,11 +579,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"345 Shirt\"" f.Query = "faces:\"345 Shirt\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -808,11 +593,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"faces555 Blue\"" f.Query = "faces:\"faces555 Blue\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -826,11 +606,6 @@ func TestPhotosQueryFaces(t *testing.T) {
f.Query = "faces:\"Route 66\"" f.Query = "faces:\"Route 66\""
f.Primary = true f.Primary = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

View File

@@ -31,11 +31,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:yes" f.Query = "favorite:yes"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -45,11 +40,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:false" f.Query = "favorite:false"
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos2, _, err2 := Photos(f) photos2, _, err2 := Photos(f)
if err2 != nil { if err2 != nil {
@@ -63,11 +53,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"%gold\"" f.Query = "favorite:\"%gold\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -81,11 +66,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"I love % dog\"" f.Query = "favorite:\"I love % dog\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -99,11 +79,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"sale%\"" f.Query = "favorite:\"sale%\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -117,11 +92,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"&IlikeFood\"" f.Query = "favorite:\"&IlikeFood\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -136,11 +106,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Pets & Dogs\"" f.Query = "favorite:\"Pets & Dogs\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -154,16 +119,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Light&\"" f.Query = "favorite:\"Light&\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -178,11 +133,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"'Family\"" f.Query = "favorite:\"'Family\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -197,11 +147,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Mother's Day\"" f.Query = "favorite:\"Mother's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -216,11 +161,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Ice Cream'\"" f.Query = "favorite:\"Ice Cream'\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -235,11 +175,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"*Forrest\"" f.Query = "favorite:\"*Forrest\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -254,11 +189,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"My*Kids\"" f.Query = "favorite:\"My*Kids\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -273,11 +203,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Yoga***\"" f.Query = "favorite:\"Yoga***\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -292,11 +217,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"|Banana\"" f.Query = "favorite:\"|Banana\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -311,11 +231,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Red|Green\"" f.Query = "favorite:\"Red|Green\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -330,11 +245,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Blue|\"" f.Query = "favorite:\"Blue|\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -349,11 +259,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"345 Shirt\"" f.Query = "favorite:\"345 Shirt\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -368,11 +273,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Color555 Blue\"" f.Query = "favorite:\"Color555 Blue\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -387,11 +287,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Route 66\"" f.Query = "favorite:\"Route 66\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -406,11 +301,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Route 66 & Father's Day\"" f.Query = "favorite:\"Route 66 & Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {
@@ -425,11 +315,6 @@ func TestPhotosQueryFavorite(t *testing.T) {
f.Query = "favorite:\"Route %66 | *Father's Day\"" f.Query = "favorite:\"Route %66 | *Father's Day\""
f.Merged = true f.Merged = true
// Parse query string and filter.
if err := f.ParseQueryString(); err != nil {
t.Fatal(err)
}
photos, _, err := Photos(f) photos, _, err := Photos(f)
if err != nil { if err != nil {

Some files were not shown because too many files have changed in this diff Show More