├── CONTRIBUTING.md
├── COPYING
├── LICENSE-2.0.txt
├── README
├── app.build.js
├── r.js
└── static
├── admin.html
├── css
└── index.css
├── images
├── favicon.ico
└── play.png
├── index.html
└── js
├── admin-main.js
├── main.js
├── third-party
├── jquery.parseparams.js
├── lscache.js
├── parseUri.js
└── require-jquery.js
└── ytdl
├── auth.js
├── config.js
├── constants.js
├── globals.js
├── load.js
├── panels
├── admin.js
├── approved.js
├── embed-codes.js
├── existing.js
├── login.js
├── logout.js
├── pending.js
├── postupload.js
├── rejected.js
├── select.js
├── upload.js
└── webcam.js
├── player.js
└── utils.js
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute #
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | a just a few small guidelines you need to follow.
5 |
6 |
7 | ## Contributor License Agreement ##
8 |
9 | Contributions to any Google project must be accompanied by a Contributor
10 | License Agreement. This is not a copyright **assignment**, it simply gives
11 | Google permission to use and redistribute your contributions as part of the
12 | project.
13 |
14 | * If you are an individual writing original source code and you're sure you
15 | own the intellectual property, then you'll need to sign an [individual
16 | CLA][].
17 |
18 | * If you work for a company that wants to allow you to contribute your work,
19 | then you'll need to sign a [corporate CLA][].
20 |
21 | You generally only need to submit a CLA once, so if you've already submitted
22 | one (even if it was for a different project), you probably don't need to do it
23 | again.
24 |
25 | [individual CLA]: https://developers.google.com/open-source/cla/individual
26 | [corporate CLA]: https://developers.google.com/open-source/cla/corporate
27 |
28 |
29 | ## Submitting a patch ##
30 |
31 | 1. It's generally best to start by opening a new issue describing the bug or
32 | feature you're intending to fix. Even if you think it's relatively minor,
33 | it's helpful to know what people are working on. Mention in the initial
34 | issue that you are planning to work on that bug or feature so that it can
35 | be assigned to you.
36 |
37 | 1. Follow the normal process of [forking][] the project, and setup a new
38 | branch to work in. It's important that each group of changes be done in
39 | separate branches in order to ensure that a pull request only includes the
40 | commits related to that bug or feature.
41 |
42 | 1. Go makes it very simple to ensure properly formatted code, so always run
43 | `go fmt` on your code before committing it. You should also run
44 | [golint][] over your code. As noted in the [golint readme][], it's not
45 | strictly necessary that your code be completely "lint-free", but this will
46 | help you find common style issues.
47 |
48 | 1. Any significant changes should almost always be accompanied by tests. The
49 | project already has good test coverage, so look at some of the existing
50 | tests if you're unsure how to go about it. [gocov][] and [gocov-html][]
51 | are invaluable tools for seeing which parts of your code aren't being
52 | exercised by your tests.
53 |
54 | 1. Do your best to have [well-formed commit messages][] for each change.
55 | This provides consistency throughout the project, and ensures that commit
56 | messages are able to be formatted properly by various git tools.
57 |
58 | 1. Finally, push the commits to your fork and submit a [pull request][].
59 |
60 | [forking]: https://help.github.com/articles/fork-a-repo
61 | [golint]: https://github.com/golang/lint
62 | [golint readme]: https://github.com/golang/lint/blob/master/README
63 | [gocov]: https://github.com/axw/gocov
64 | [gocov-html]: https://github.com/matm/gocov-html
65 | [well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
66 | [squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
67 | [pull request]: https://help.github.com/articles/creating-a-pull-request
68 |
69 |
70 | ## Other notes on code organization ##
71 |
72 | Currently, everything is defined in the main `github` package, with API methods
73 | broken into separate service objects. These services map directly to how
74 | the [GitHub API documentation][] is organized, so use that as your guide for
75 | where to put new methods.
76 |
77 | Sub-service (e.g. [Repo Hooks][]) implementations are split into separate files
78 | based on the APIs they provide. These files are named service_api.go (e.g.
79 | repos_hooks.go) to describe the API to service mappings.
80 |
81 | [GitHub API documentation]: http://developer.github.com/v3/
82 | [Repo Hooks]: http://developer.github.com/v3/repos/hooks/
83 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2012 Google, Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/LICENSE-2.0.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Please visit http://code.google.com/p/youtube-direct-lite/ for the most up to date information
2 | on deploying and using YouTube Direct Lite.
3 |
4 | If you are using a local deployment, it is recommended that you concatenate and minify all the
5 | JavaScript source files for performance reasons. You can do this by running
6 |
7 | node r.js -o app.build.js
8 |
9 | from within this top-level directory; it will output a static-min/ directory containing the
10 | optimized JavaScript, which you can then serve. More information about this process, including
11 | the dependencies you need to install to run those commands, can be found at
12 |
13 | http://requirejs.org/docs/optimization.html
--------------------------------------------------------------------------------
/app.build.js:
--------------------------------------------------------------------------------
1 | ({
2 | appDir: 'static',
3 | baseUrl: 'js',
4 | dir: 'static-min',
5 | paths: {jquery: 'empty:'},
6 | modules: [
7 | {name: 'main'},
8 | {name: 'admin-main'}
9 | ]
10 | })
--------------------------------------------------------------------------------
/static/admin.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | YouTube Direct Lite Admin
5 |
6 |
7 |
8 |
9 |
10 |
11 |
65 |
66 |
--------------------------------------------------------------------------------
/static/js/admin-main.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | requirejs([
18 | 'jquery',
19 | 'ytdl/load',
20 | 'ytdl/auth'
21 | ], function($, load, auth) {
22 | auth.initAuth();
23 |
24 | $(function() {
25 | load.onLoad('admin');
26 | });
27 | });
--------------------------------------------------------------------------------
/static/js/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | requirejs([
18 | 'jquery',
19 | 'ytdl/load',
20 | 'ytdl/auth'
21 | ], function($, load, auth) {
22 | auth.initAuth();
23 |
24 | $(function() {
25 | load.onLoad('upload');
26 | });
27 | });
--------------------------------------------------------------------------------
/static/js/third-party/jquery.parseparams.js:
--------------------------------------------------------------------------------
1 | /**
2 | * $.parseParams - parse query string paramaters into an object.
3 | */
4 | (function($) {
5 | var re = /([^&=]+)=?([^&]*)/g;
6 | var decodeRE = /\+/g; // Regex for replacing addition symbol with a space
7 | var decode = function (str) { return decodeURIComponent( str.replace(decodeRE, " ") ); };
8 | $.parseParams = function(query) {
9 | var params = {}, e;
10 | while ( e = re.exec(query) ) params[ decode(e[1]) ] = decode( e[2] );
11 | return params;
12 | };
13 | })(jQuery);
--------------------------------------------------------------------------------
/static/js/third-party/lscache.js:
--------------------------------------------------------------------------------
1 | /**
2 | * lscache library
3 | * Copyright (c) 2011, Pamela Fox
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | /*jshint undef:true, browser:true */
19 |
20 | /**
21 | * Creates a namespace for the lscache functions.
22 | */
23 | var lscache = function() {
24 |
25 | // Prefix for all lscache keys
26 | var CACHE_PREFIX = 'lscache-';
27 |
28 | // Suffix for the key name on the expiration items in localStorage
29 | var CACHE_SUFFIX = '-cacheexpiration';
30 |
31 | // expiration date radix (set to Base-36 for most space savings)
32 | var EXPIRY_RADIX = 10;
33 |
34 | // time resolution in minutes
35 | var EXPIRY_UNITS = 60 * 1000;
36 |
37 | // ECMAScript max Date (epoch + 1e8 days)
38 | var MAX_DATE = Math.floor(8.64e15/EXPIRY_UNITS);
39 |
40 | var cachedStorage;
41 | var cachedJSON;
42 |
43 | // Determines if localStorage is supported in the browser;
44 | // result is cached for better performance instead of being run each time.
45 | // Feature detection is based on how Modernizr does it;
46 | // it's not straightforward due to FF4 issues.
47 | // It's not run at parse-time as it takes 200ms in Android.
48 | function supportsStorage() {
49 | var key = '__lscachetest__';
50 | var value = key;
51 |
52 | if (cachedStorage !== undefined) {
53 | return cachedStorage;
54 | }
55 |
56 | try {
57 | setItem(key, value);
58 | removeItem(key);
59 | cachedStorage = true;
60 | } catch (exc) {
61 | cachedStorage = false;
62 | }
63 | return cachedStorage;
64 | }
65 |
66 | // Determines if native JSON (de-)serialization is supported in the browser.
67 | function supportsJSON() {
68 | /*jshint eqnull:true */
69 | if (cachedJSON === undefined) {
70 | cachedJSON = (window.JSON != null);
71 | }
72 | return cachedJSON;
73 | }
74 |
75 | /**
76 | * Returns the full string for the localStorage expiration item.
77 | * @param {String} key
78 | * @return {string}
79 | */
80 | function expirationKey(key) {
81 | return key + CACHE_SUFFIX;
82 | }
83 |
84 | /**
85 | * Returns the number of minutes since the epoch.
86 | * @return {number}
87 | */
88 | function currentTime() {
89 | return Math.floor((new Date().getTime())/EXPIRY_UNITS);
90 | }
91 |
92 | /**
93 | * Wrapper functions for localStorage methods
94 | */
95 |
96 | function getItem(key) {
97 | return localStorage.getItem(CACHE_PREFIX + key);
98 | }
99 |
100 | function setItem(key, value) {
101 | // Fix for iPad issue - sometimes throws QUOTA_EXCEEDED_ERR on setItem.
102 | localStorage.removeItem(CACHE_PREFIX + key);
103 | localStorage.setItem(CACHE_PREFIX + key, value);
104 | }
105 |
106 | function removeItem(key) {
107 | localStorage.removeItem(CACHE_PREFIX + key);
108 | }
109 |
110 | return {
111 |
112 | /**
113 | * Stores the value in localStorage. Expires after specified number of minutes.
114 | * @param {string} key
115 | * @param {Object|string} value
116 | * @param {number} time
117 | */
118 | set: function(key, value, time) {
119 | if (!supportsStorage()) return;
120 |
121 | // If we don't get a string value, try to stringify
122 | // In future, localStorage may properly support storing non-strings
123 | // and this can be removed.
124 | if (typeof value !== 'string') {
125 | if (!supportsJSON()) return;
126 | try {
127 | value = JSON.stringify(value);
128 | } catch (e) {
129 | // Sometimes we can't stringify due to circular refs
130 | // in complex objects, so we won't bother storing then.
131 | return;
132 | }
133 | }
134 |
135 | try {
136 | setItem(key, value);
137 | } catch (e) {
138 | if (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
139 | // If we exceeded the quota, then we will sort
140 | // by the expire time, and then remove the N oldest
141 | var storedKeys = [];
142 | var storedKey;
143 | for (var i = 0; i < localStorage.length; i++) {
144 | storedKey = localStorage.key(i);
145 |
146 | if (storedKey.indexOf(CACHE_PREFIX) === 0 && storedKey.indexOf(CACHE_SUFFIX) < 0) {
147 | var mainKey = storedKey.substr(CACHE_PREFIX.length);
148 | var exprKey = expirationKey(mainKey);
149 | var expiration = getItem(exprKey);
150 | if (expiration) {
151 | expiration = parseInt(expiration, EXPIRY_RADIX);
152 | } else {
153 | // TODO: Store date added for non-expiring items for smarter removal
154 | expiration = MAX_DATE;
155 | }
156 | storedKeys.push({
157 | key: mainKey,
158 | size: (getItem(mainKey)||'').length,
159 | expiration: expiration
160 | });
161 | }
162 | }
163 | // Sorts the keys with oldest expiration time last
164 | storedKeys.sort(function(a, b) { return (b.expiration-a.expiration); });
165 |
166 | var targetSize = (value||'').length;
167 | while (storedKeys.length && targetSize > 0) {
168 | storedKey = storedKeys.pop();
169 | removeItem(storedKey.key);
170 | removeItem(expirationKey(storedKey.key));
171 | targetSize -= storedKey.size;
172 | }
173 | try {
174 | setItem(key, value);
175 | } catch (e) {
176 | // value may be larger than total quota
177 | return;
178 | }
179 | } else {
180 | // If it was some other error, just give up.
181 | return;
182 | }
183 | }
184 |
185 | // If a time is specified, store expiration info in localStorage
186 | if (time) {
187 | setItem(expirationKey(key), (currentTime() + time).toString(EXPIRY_RADIX));
188 | } else {
189 | // In case they previously set a time, remove that info from localStorage.
190 | removeItem(expirationKey(key));
191 | }
192 | },
193 |
194 | /**
195 | * Retrieves specified value from localStorage, if not expired.
196 | * @param {string} key
197 | * @return {string|Object}
198 | */
199 | get: function(key) {
200 | if (!supportsStorage()) return null;
201 |
202 | // Return the de-serialized item if not expired
203 | var exprKey = expirationKey(key);
204 | var expr = getItem(exprKey);
205 |
206 | if (expr) {
207 | var expirationTime = parseInt(expr, EXPIRY_RADIX);
208 |
209 | // Check if we should actually kick item out of storage
210 | if (currentTime() >= expirationTime) {
211 | removeItem(key);
212 | removeItem(exprKey);
213 | return null;
214 | }
215 | }
216 |
217 | // Tries to de-serialize stored value if its an object, and returns the normal value otherwise.
218 | var value = getItem(key);
219 | if (!value || !supportsJSON()) {
220 | return value;
221 | }
222 |
223 | try {
224 | // We can't tell if its JSON or a string, so we try to parse
225 | return JSON.parse(value);
226 | } catch (e) {
227 | // If we can't parse, it's probably because it isn't an object
228 | return value;
229 | }
230 | },
231 |
232 | /**
233 | * Removes a value from localStorage.
234 | * Equivalent to 'delete' in memcache, but that's a keyword in JS.
235 | * @param {string} key
236 | */
237 | remove: function(key) {
238 | if (!supportsStorage()) return null;
239 | removeItem(key);
240 | removeItem(expirationKey(key));
241 | },
242 |
243 | /**
244 | * Returns whether local storage is supported.
245 | * Currently exposed for testing purposes.
246 | * @return {boolean}
247 | */
248 | supported: function() {
249 | return supportsStorage();
250 | },
251 |
252 | /**
253 | * Flushes all lscache items and expiry markers without affecting rest of localStorage
254 | */
255 | flush: function() {
256 | if (!supportsStorage()) return;
257 |
258 | // Loop in reverse as removing items will change indices of tail
259 | for (var i = localStorage.length-1; i >= 0 ; --i) {
260 | var key = localStorage.key(i);
261 | if (key.indexOf(CACHE_PREFIX) === 0) {
262 | localStorage.removeItem(key);
263 | }
264 | }
265 | }
266 | };
267 | }();
268 |
--------------------------------------------------------------------------------
/static/js/third-party/parseUri.js:
--------------------------------------------------------------------------------
1 | // parseUri 1.2.2
2 | // (c) Steven Levithan
3 | // MIT License
4 |
5 | function parseUri (str) {
6 | var o = parseUri.options,
7 | m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
8 | uri = {},
9 | i = 14;
10 |
11 | while (i--) uri[o.key[i]] = m[i] || "";
12 |
13 | uri[o.q.name] = {};
14 | uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
15 | if ($1) uri[o.q.name][$1] = $2;
16 | });
17 |
18 | return uri;
19 | };
20 |
21 | parseUri.options = {
22 | strictMode: false,
23 | key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
24 | q: {
25 | name: "queryKey",
26 | parser: /(?:^|&)([^&=]*)=?([^&]*)/g
27 | },
28 | parser: {
29 | strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
30 | loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/static/js/ytdl/auth.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', './utils', './constants', './config', './globals'], function($, utils, constants, config, globals) {
18 | var auth = {
19 | initAuth: function() {
20 | window[constants.CLIENT_LIB_LOAD_CALLBACK] = function() {
21 | gapi.auth.init(function() {
22 | if (lscache.get(constants.DISPLAY_NAME_CACHE_KEY)) {
23 | window.setTimeout(function() {
24 | gapi.auth.authorize({
25 | client_id: config.OAUTH2_CLIENT_ID,
26 | scope: [constants.OAUTH2_SCOPE],
27 | immediate: true
28 | }, auth.onAuthResult);
29 | }, 1);
30 | } else {
31 | utils.redirect('login');
32 | }
33 | });
34 | };
35 |
36 | $.getScript(constants.CLIENT_LIB_URL + constants.CLIENT_LIB_LOAD_CALLBACK);
37 | },
38 |
39 | onAuthResult: function(authResult) {
40 | if (authResult) {
41 | gapi.client.load(constants.YOUTUBE_API_SERVICE_NAME, constants.YOUTUBE_API_VERSION, auth.onYouTubeClientLoad);
42 | } else {
43 | lscache.flush();
44 | utils.redirect('login');
45 | }
46 | },
47 |
48 | onYouTubeClientLoad: function() {
49 | var nextState = globals.hashParams.state || '';
50 | if (nextState == 'login') {
51 | nextState = '';
52 | }
53 |
54 | if (lscache.get(constants.DISPLAY_NAME_CACHE_KEY)) {
55 | utils.redirect(nextState);
56 | } else {
57 | var request = gapi.client[constants.YOUTUBE_API_SERVICE_NAME].channels.list({
58 | mine: true,
59 | part: 'snippet,contentDetails,status'
60 | });
61 | request.execute(function(response) {
62 | if (utils.itemsInResponse(response)) {
63 | if (response.items[0].status.isLinked) {
64 | lscache.set(constants.UPLOADS_LIST_ID_CACHE_KEY, response.items[0].contentDetails.relatedPlaylists.uploads);
65 | lscache.set(constants.DISPLAY_NAME_CACHE_KEY, response.items[0].snippet.title);
66 | lscache.set(constants.PROFILE_PICTURE_CACHE_KEY, response.items[0].snippet.thumbnails.default.url);
67 | utils.redirect(nextState);
68 | } else {
69 | utils.showHtmlMessage('Your account cannot upload videos. Please visit https://www.youtube.com/signin?next=/create_channel to add a YouTube channel to your account, and try again.');
70 | }
71 | } else {
72 | utils.showMessage('Unable to retrieve channel info. ' + utils.getErrorResponseString(response));
73 | }
74 | });
75 | }
76 | }
77 | };
78 |
79 | return auth;
80 | });
--------------------------------------------------------------------------------
/static/js/ytdl/config.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define({
18 | // REQUIRED
19 | // See https://developers.google.com/api-client-library/javascript/features/authentication
20 | // for instructions on registering for OAuth 2.
21 | // After generating your OAuth 2 client id, you MUST then visit the "Services" tab of
22 | // https://code.google.com/apis/console/ find the entry for "YouTube Data API v3"
23 | // and flip it to "ON".
24 | OAUTH2_CLIENT_ID: '',
25 |
26 | // REQUIRED
27 | // Register at https://code.google.com/apis/youtube/dashboard/gwt/index.html to get your own key.
28 | DEVELOPER_KEY: ''
29 |
30 | // If you'd like to enable Google Analytics statistics to your YouTube Direct Lite instance,
31 | // register for a Google Analytics account and enter your id code below.
32 | //,GOOGLE_ANALYTICS_ID: 'UA-########-#'
33 |
34 | // Setting any or all of these three fields are optional.
35 | // If set then the value(s) will be used for new video uploads, and your users won't be prompted for the corresponding fields on the video upload form.
36 | //,VIDEO_TITLE: 'Video Submission'
37 | //,VIDEO_DESCRIPTION: 'This is a video submission.'
38 | // Make sure that this corresponds to an assignable category!
39 | // See https://developers.google.com/youtube/2.0/reference#YouTube_Category_List
40 | //,VIDEO_CATEGORY: 'People'
41 | });
--------------------------------------------------------------------------------
/static/js/ytdl/constants.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define({
18 | CATEGORIES_CACHE_EXPIRATION_MINUTES: 3 * 24 * 60,
19 | CATEGORIES_CACHE_KEY: 'categories',
20 | DISPLAY_NAME_CACHE_KEY: 'display_name',
21 | UPLOADS_LIST_ID_CACHE_KEY: 'uploads_list_id',
22 | PROFILE_PICTURE_CACHE_KEY: 'profile_picture',
23 | GENERIC_PROFILE_PICTURE_URL: '//s.ytimg.com/yt/img/no_videos_140-vfl1fDI7-.png',
24 | OAUTH2_TOKEN_TYPE: 'Bearer',
25 | OAUTH2_SCOPE: 'https://gdata.youtube.com',
26 | GDATA_SERVER: 'https://gdata.youtube.com',
27 | CLIENT_LIB_LOAD_CALLBACK: 'onClientLibReady',
28 | CLIENT_LIB_URL: 'https://apis.google.com/js/client.js?onload=',
29 | YOUTUBE_API_SERVICE_NAME: 'youtube',
30 | YOUTUBE_API_VERSION: 'v3',
31 | PAGE_SIZE: 50,
32 | MAX_ITEMS_TO_RETRIEVE: 200,
33 | FEED_CACHE_MINUTES: 5,
34 | STATE_CACHE_MINUTES: 15,
35 | MAX_KEYWORD_LENGTH: 30,
36 | KEYWORD_UPDATE_XML_TEMPLATE: ' {0}',
37 | WIDGET_EMBED_CODE: '',
38 | PLAYLIST_EMBED_CODE: '',
39 | SUBMISSION_RSS_FEED: 'https://gdata.youtube.com/feeds/api/videos?v=2&alt=rss&orderby=published&category=%7Bhttp%3A%2F%2Fgdata.youtube.com%2Fschemas%2F2007%2Fkeywords.cat%7D{0}',
40 | DEFAULT_KEYWORD: 'ytdl',
41 | WEBCAM_VIDEO_TITLE: 'Webcam Submission',
42 | WEBCAM_VIDEO_DESCRIPTION: 'Uploaded via a webcam.',
43 | REJECTED_VIDEOS_PLAYLIST: 'Rejected YTDL Submissions',
44 | NO_THUMBNAIL_URL: '//i.ytimg.com/vi/hqdefault.jpg',
45 | VIDEO_CONTAINER_TEMPLATE: '
{title}({duration})
Uploaded on {uploadedDate}
',
46 | VIDEO_LI_TEMPLATE: '
{3}({5})
Uploaded on {4}
',
47 | ADMIN_VIDEO_LI_TEMPLATE: '
{buttonsHtml}
{title}({duration})
Uploaded on {uploadedDate} by {uploader}
',
48 | PLAYLIST_LI_TEMPLATE: '
{playlistName}
'
49 | });
--------------------------------------------------------------------------------
/static/js/ytdl/globals.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define({
18 | parsedUrl: parseUri(window.location.href),
19 | rejectedPlaylistId: ''
20 | });
--------------------------------------------------------------------------------
/static/js/ytdl/load.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define([
18 | 'jquery',
19 | './constants',
20 | './globals',
21 | './utils',
22 | './config',
23 | './player',
24 | 'ytdl/panels/upload',
25 | 'ytdl/panels/existing',
26 | 'ytdl/panels/login',
27 | 'ytdl/panels/logout',
28 | 'ytdl/panels/postupload',
29 | 'ytdl/panels/select',
30 | 'ytdl/panels/webcam',
31 | 'ytdl/panels/admin',
32 | 'ytdl/panels/embed-codes',
33 | 'ytdl/panels/pending',
34 | 'ytdl/panels/approved',
35 | 'ytdl/panels/rejected'
36 | ], function($, constants, globals, utils, config, player, upload) {
37 | return {
38 | onLoad: function(defaultTab) {
39 | window._gaq = window._gaq || [];
40 |
41 | if (config.GOOGLE_ANALYTICS_ID) {
42 | window._gaq.push(['_setAccount', config.GOOGLE_ANALYTICS_ID]);
43 |
44 | var analyticsScriptSrc = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
45 | $.getScript(analyticsScriptSrc);
46 | }
47 |
48 | if (!config.OAUTH2_CLIENT_ID || !config.DEVELOPER_KEY) {
49 | utils.showHtmlMessage('YouTube Direct Lite isn\'t configured. Please see the setup guide for more info.');
50 | return;
51 | }
52 |
53 | if (!$.support.cors) {
54 | if (defaultTab == 'admin') {
55 | utils.showHtmlMessage('Unfortunately, your browser is not supported. Please try visiting this page using a recent version of Firefox, Safari, Opera, or Chrome.');
56 | window._gaq.push(['_trackPageview']);
57 | return;
58 | } else {
59 | defaultTab = 'existing';
60 | delete upload.init;
61 | delete upload.display;
62 | $('#upload-panel').html('
Your browser does not meet the requirements needed to upload a new video. Please choose one of the other options.
');
63 | }
64 | }
65 |
66 | utils.updateHashParams();
67 |
68 | $('body').on({
69 | click: function() {
70 | utils.redirect($(this).attr('data-state'), $(this).attr('data-playlist-id'));
71 | }
72 | }, '[data-state]');
73 |
74 | $('#message').click(function() {
75 | $(this).hide();
76 | });
77 |
78 | $('body').on({
79 | click: function() {
80 | player.playVideo(this, $(this).data('video-id'));
81 | },
82 | mouseenter: function() {
83 | $(this).find('.play-overlay').fadeIn();
84 | },
85 | mouseleave: function() {
86 | $(this).find('.play-overlay').fadeOut();
87 | }
88 | }, '.thumbnail-container');
89 |
90 | $(window).bind('hashchange', function() {
91 | utils.updateHashParams();
92 | var state = globals.hashParams.state || defaultTab;
93 |
94 | $('#profile-picture').attr('src', lscache.get(constants.PROFILE_PICTURE_CACHE_KEY) || constants.GENERIC_PROFILE_PICTURE_URL);
95 | var displayName = lscache.get(constants.DISPLAY_NAME_CACHE_KEY);
96 | $('#display-name').text(displayName);
97 | if (displayName) {
98 | $('.login-required').show();
99 | } else {
100 | $('.login-required').hide();
101 | }
102 |
103 | var panel;
104 | try {
105 | panel = require(utils.format('ytdl/panels/{0}', state));
106 | } catch (e) {
107 | utils.showMessage(utils.format('Unknown panel: {0}', state));
108 | return;
109 | }
110 |
111 | utils.hideMessage();
112 |
113 | if (panel.needsPlaylist && !globals.hashParams.playlist) {
114 | utils.showMessage('The "playlist" URL parameter is missing.');
115 | return;
116 | }
117 |
118 | if ('init' in panel) {
119 | panel.init();
120 | delete panel.init;
121 | }
122 |
123 | if ('display' in panel) {
124 | panel.display();
125 | }
126 |
127 | $('.panel').hide();
128 | $(utils.format('#{0}-panel', state)).show();
129 | $('#tabs > li').removeClass('selected');
130 | $(utils.format('#tabs > li[data-state={0}]', state)).addClass('selected');
131 |
132 | window._gaq.push(['_trackPageview', utils.format('{0}#state={1}', location.pathname, state)]);
133 | });
134 | }
135 | };
136 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/admin.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants'], function($, utils, constants) {
18 | var admin = {
19 | init: function() {
20 | admin.attachClickHandler();
21 | },
22 |
23 | display: function() {
24 | $('#tabs').hide();
25 | $('#switch').hide();
26 | $('#moderation-message').hide();
27 |
28 | utils.getPlaylists(function(playlists) {
29 | var lis = [];
30 | $.each(playlists, function() {
31 | lis.push(utils.format(constants.PLAYLIST_LI_TEMPLATE, {
32 | playlistId: this.id,
33 | playlistName: this.snippet.title
34 | }));
35 | });
36 | $('#playlists').html(lis.sort().join(''));
37 | $('#playlists').append('
');
38 |
39 | admin.attachClickHandler();
40 | });
41 | },
42 |
43 | // TODO: This is a bit of a hack to work around the fact that the #create-playlist button is
44 | // recreated each time display() is called. There's obviously better ways of dealing with that.
45 | attachClickHandler: function() {
46 | $('#create-playlist').click(function() {
47 | $(this).attr('disabled', true);
48 | var playlistName = $('#new-playlist-name').val();
49 | if (playlistName) {
50 | utils.addPlaylist(playlistName, false, function(playlistId) {
51 | utils.redirect('embed-codes', playlistId);
52 | });
53 | } else {
54 | utils.showMessage('Please enter a name for the playlist.');
55 | }
56 |
57 | $(this).removeAttr('disabled');
58 | });
59 | }
60 | };
61 |
62 | return admin;
63 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/approved.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals'], function($, utils, constants, globals) {
18 | return {
19 | needsPlaylist: true,
20 | init: function() {
21 | $('body').on({
22 | click: function() {
23 | var button = $(this);
24 | button.attr('disabled', true);
25 | utils.addVideoToPlaylist(globals.rejectedPlaylistId, button.attr('data-video-id'));
26 | utils.removeVideoFromPlaylist(button.attr('data-edit-url'));
27 |
28 | window._gaq.push(['_trackEvent', 'Admin', 'Reject']);
29 |
30 | utils.animateModeration($(this).closest('li'), $('li[data-state=rejected]'));
31 | }
32 | }, '#approved-panel input.reject');
33 | },
34 | display: function() {
35 | $('#tabs').show();
36 | $('#switch').show();
37 |
38 | utils.getPlaylists(function() {
39 | utils.getStateOfSubmissions(function(state) {
40 | if (state) {
41 | var lis = [];
42 |
43 | $.each(state.approvedIds, function() {
44 | var metadata = state.videoIdToMetadata[this];
45 | if (metadata) {
46 | var editUrl = state.videoIdToPlaylistEntryId[this];
47 | metadata.buttonsHtml = utils.format('', {
48 | videoId: this,
49 | editUrl: editUrl
50 | });
51 |
52 | lis.push(utils.format(constants.ADMIN_VIDEO_LI_TEMPLATE, metadata));
53 | }
54 | });
55 |
56 | $('#approved-videos').html(lis.join(''));
57 |
58 | $('#moderation-message').text(utils.format('{0} {1} approved.', lis.length, lis.length == 1 ? 'video is' : 'videos are')).show();
59 | } else {
60 | utils.showMessage(utils.format('Unable to determine submission state. Is the "{0}" playlist missing?', constants.REJECTED_VIDEOS_PLAYLIST));
61 | }
62 | });
63 | });
64 | }
65 | };
66 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/embed-codes.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals'], function($, utils, constants, globals) {
18 | return {
19 | needsPlaylist: true,
20 | display: function() {
21 | $('#tabs').show();
22 | $('#switch').show();
23 | $('#moderation-message').hide();
24 |
25 | $('#widget-embed-code').text(utils.format(constants.WIDGET_EMBED_CODE, utils.currentUrlWithoutParams().replace('admin.html', 'index.html'), globals.hashParams.playlist));
26 | $('#playlist-embed-code').text(utils.format(constants.PLAYLIST_EMBED_CODE, globals.hashParams.playlist));
27 | $('#rss-feed').attr('href', utils.format(constants.SUBMISSION_RSS_FEED, utils.generateKeywordFromPlaylistId(globals.hashParams.playlist)));
28 | }
29 | };
30 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/existing.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals'], function($, utils, constants, globals) {
18 | return {
19 | needsPlaylist: true,
20 | init: function() {
21 | $('#existing-panel').on({
22 | click: function() {
23 | $(this).attr('disabled', true);
24 | var video = $(this).data('video');
25 |
26 | if (!('tags' in video.snippet)) {
27 | video.snippet.tags = [];
28 | }
29 |
30 | if ($.inArray(constants.DEFAULT_KEYWORD, video.snippet.tags) == -1) {
31 | video.snippet.tags.push(constants.DEFAULT_KEYWORD);
32 | }
33 |
34 | var keyword = utils.generateKeywordFromPlaylistId(globals.hashParams.playlist);
35 | if ($.inArray(keyword, video.snippet.tags) == -1) {
36 | video.snippet.tags.push(keyword);
37 | }
38 |
39 | delete video.contentDetails;
40 | delete video.status;
41 |
42 | var request = gapi.client[constants.YOUTUBE_API_SERVICE_NAME].videos.update({
43 | part: 'snippet',
44 | resource: video
45 | });
46 | request.execute(function(response) {
47 | if ('error' in response) {
48 | utils.showMessage('Submission failed. ' + utils.getErrorResponseString(response));
49 | $(this).removeAttr('disabled');
50 | window._gaq.push(['_trackEvent', 'Submission', 'Existing', 'Error']);
51 | } else {
52 | utils.showMessage('Your submission was received.');
53 | window._gaq.push(['_trackEvent', 'Submission', 'Existing', 'Success']);
54 | }
55 | });
56 | }
57 | }, '.submit-video-button');
58 |
59 | utils.getAllItems('playlistItems', {
60 | part: 'snippet',
61 | playlistId: lscache.get(constants.UPLOADS_LIST_ID_CACHE_KEY)
62 | }, function(items) {
63 | var videoIds = $.map(items, function(item) {
64 | return item.snippet.resourceId.videoId;
65 | });
66 | utils.getInfoForVideoIds(videoIds, function(videos) {
67 | videos.sort(function(a, b) {
68 | return a.snippet.publishedAt > b.snippet.publishedAt ? -1 : 1;
69 | });
70 |
71 | $.each(videos, function() {
72 | if (this.status.uploadStatus != 'processed' || this.status.privacyStatus != 'public') {
73 | return true;
74 | }
75 |
76 | var videoLi = $(utils.format(constants.VIDEO_CONTAINER_TEMPLATE, {
77 | thumbnailUrl: this.snippet.thumbnails.high.url,
78 | uploadedDate: new Date(this.snippet.publishedAt).toDateString(),
79 | duration: utils.formatPeriodOfTime(this.contentDetails.duration),
80 | title: this.snippet.title,
81 | videoId: this.id
82 | }));
83 | videoLi.find('.submit-video-button').data('video', this);
84 | videoLi.appendTo('#existing-videos');
85 | });
86 | });
87 | });
88 | }
89 | };
90 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/login.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../auth', '../constants', '../config'], function($, auth, constants, config) {
18 | return {
19 | init: function() {
20 | $('#login').click(function() {
21 | gapi.auth.authorize({
22 | client_id: config.OAUTH2_CLIENT_ID,
23 | scope: [constants.OAUTH2_SCOPE],
24 | immediate: false
25 | }, auth.onAuthResult);
26 | });
27 | }
28 | };
29 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/logout.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['../utils'], function(utils) {
18 | return {
19 | display: function() {
20 | lscache.flush();
21 | utils.redirect('login');
22 | }
23 | };
24 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/pending.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals'], function($, utils, constants, globals) {
18 | return {
19 | needsPlaylist: true,
20 | init: function() {
21 | $('body').on({
22 | click: function() {
23 | $(this).attr('disabled', true);
24 | utils.addVideoToPlaylist(globals.hashParams.playlist, $(this).attr('data-video-id'));
25 |
26 | window._gaq.push(['_trackEvent', 'Admin', 'Approve']);
27 |
28 | utils.animateModeration($(this).closest('li'), $('li[data-state=approved]'));
29 | }
30 | }, '#pending-panel input.approve');
31 |
32 | $('body').on({
33 | click: function() {
34 | $(this).attr('disabled', true);
35 | utils.addVideoToPlaylist(globals.rejectedPlaylistId, $(this).attr('data-video-id'));
36 |
37 | window._gaq.push(['_trackEvent', 'Admin', 'Reject']);
38 |
39 | utils.animateModeration($(this).closest('li'), $('li[data-state=rejected]'));
40 | }
41 | }, '#pending-panel input.reject');
42 | },
43 | display: function() {
44 | $('#tabs').show();
45 | $('#switch').show();
46 |
47 | utils.getPlaylists(function() {
48 | utils.getStateOfSubmissions(function(state) {
49 | if (state) {
50 | var lis = [];
51 |
52 | $.each(state.pendingIds, function() {
53 | var metadata = state.videoIdToMetadata[this];
54 | if (metadata) {
55 | metadata.buttonsHtml = utils.format('', this);
56 |
57 | lis.push(utils.format(constants.ADMIN_VIDEO_LI_TEMPLATE, metadata));
58 | }
59 | });
60 |
61 | $('#pending-videos').html(lis.join(''));
62 |
63 | $('#moderation-message').text(utils.format('{0} {1} pending moderation.', lis.length, lis.length == 1 ? 'video is' : 'videos are')).show();
64 | } else {
65 | utils.showMessage(utils.format('Unable to determine submission state. Is the "{0}" playlist missing?', constants.REJECTED_VIDEOS_PLAYLIST));
66 | }
67 | });
68 | });
69 | }
70 | };
71 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/postupload.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../globals'], function($, utils, globals) {
18 | return {
19 | init: function() {
20 | var status = globals.parsedUrl.queryKey.status;
21 | if (status == 200) {
22 | var youtubeUrl = utils.format('http://youtu.be/{0}', globals.parsedUrl.queryKey.id);
23 | $('#youtube-link').attr('href', youtubeUrl);
24 | $('#upload-success').show();
25 |
26 | window._gaq.push(['_trackEvent', 'Submission', 'Upload', 'Success']);
27 | } else {
28 | $('#upload-success').hide();
29 | utils.showMessage(utils.format('Your video could not be submitted. (Error: {0})', globals.parsedUrl.queryKey.code));
30 |
31 | window._gaq.push(['_trackEvent', 'Submission', 'Upload', 'Error']);
32 | }
33 | }
34 | };
35 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/rejected.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals'], function($, utils, constants, globals) {
18 | return {
19 | needsPlaylist: true,
20 | init: function () {
21 | $('body').on({
22 | click: function() {
23 | var button = $(this);
24 | button.attr('disabled', true);
25 | utils.addVideoToPlaylist(globals.hashParams.playlist, button.attr('data-video-id'));
26 | utils.removeVideoFromPlaylist(button.attr('data-edit-url'));
27 |
28 | window._gaq.push(['_trackEvent', 'Admin', 'Approve']);
29 |
30 | utils.animateModeration($(this).closest('li'), $('li[data-state=approved]'));
31 | }
32 | }, '#rejected-panel input.approve');
33 | },
34 | display: function() {
35 | $('#tabs').show();
36 | $('#switch').show();
37 |
38 | utils.getPlaylists(function() {
39 | utils.getStateOfSubmissions(function(state) {
40 | if (state) {
41 | var lis = [];
42 |
43 | $.each(state.rejectedIds, function() {
44 | var metadata = state.videoIdToMetadata[this];
45 | if (metadata) {
46 | var editUrl = state.videoIdToPlaylistEntryId[this];
47 | metadata.buttonsHtml = utils.format('', {
48 | videoId: this,
49 | editUrl: editUrl
50 | });
51 |
52 | lis.push(utils.format(constants.ADMIN_VIDEO_LI_TEMPLATE, metadata));
53 | }
54 | });
55 |
56 | $('#rejected-videos').html(lis.join(''));
57 |
58 | $('#moderation-message').text(utils.format('{0} {1} rejected.', lis.length, lis.length == 1 ? 'video is' : 'videos are')).show();
59 | } else {
60 | utils.showMessage(utils.format('Unable to determine submission state. Is the "{0}" playlist missing?', constants.REJECTED_VIDEOS_PLAYLIST));
61 | }
62 | });
63 | });
64 | }
65 | };
66 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/select.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define({
18 | needsPlaylist: true
19 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/upload.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals', '../config'], function($, utils, constants, globals, config) {
18 | return {
19 | needsPlaylist: true,
20 | init: function() {
21 | function populateCategoriesSelect(xml) {
22 | var assignableCategories = xml.find('atom\\:category:has(yt\\:assignable), category:has(assignable)');
23 | var options = [];
24 | $.each(assignableCategories, function() {
25 | var term = $(this).attr('term');
26 | var label = $(this).attr('label');
27 | options.push(utils.format('', label, term));
28 | });
29 | $('#category').html(options.sort().join(''));
30 |
31 | }
32 |
33 | if (!config.VIDEO_CATEGORY) {
34 | $('#category-container').show();
35 | var categoriesXml = lscache.get(constants.CATEGORIES_CACHE_KEY);
36 | if (categoriesXml) {
37 | populateCategoriesSelect($(new DOMParser().parseFromString(categoriesXml, 'text/xml')));
38 | } else {
39 | $.ajax({
40 | dataType: 'xml',
41 | type: 'GET',
42 | url: utils.format('{0}/schemas/2007/categories.cat', constants.GDATA_SERVER),
43 | headers: utils.generateYouTubeApiHeaders(),
44 | success: function(responseXml) {
45 | var xmlString = new XMLSerializer().serializeToString(responseXml);
46 | lscache.set(constants.CATEGORIES_CACHE_KEY, xmlString, constants.CATEGORIES_CACHE_EXPIRATION_MINUTES);
47 | populateCategoriesSelect($(responseXml));
48 | },
49 | error: function(jqXHR) {
50 | utils.showMessage('The list of categories could not be loaded: ' + jqXHR.responseText);
51 | }
52 | });
53 | }
54 | }
55 |
56 | if (!config.VIDEO_TITLE) {
57 | $('#title-container').show();
58 | }
59 | if (!config.VIDEO_DESCRIPTION) {
60 | $('#description-container').show();
61 | }
62 |
63 | $('#upload').click(function() {
64 | $('#upload').attr('disabled', true);
65 | $('#upload').val('Uploading...');
66 |
67 | var keywordList = [ constants.DEFAULT_KEYWORD ];
68 | if (globals.hashParams.playlist) {
69 | var playlistId = globals.hashParams.playlist;
70 | var keyword = utils.generateKeywordFromPlaylistId(playlistId);
71 | keywordList.push(keyword);
72 | }
73 |
74 | var jsonBody = {
75 | data: {
76 | title: config.VIDEO_TITLE || $('#title').val(),
77 | category: config.VIDEO_CATEGORY || $('#category option:selected').val(),
78 | description: config.VIDEO_DESCRIPTION || $('#description').val(),
79 | tags: keywordList
80 | }
81 | }
82 |
83 | $.ajax({
84 | dataType: 'xml',
85 | type: 'POST',
86 | url: utils.format('{0}/action/GetUploadToken', constants.GDATA_SERVER),
87 | headers: utils.generateYouTubeApiHeaders(),
88 | data: JSON.stringify(jsonBody),
89 | contentType: 'application/json',
90 | processData: false,
91 | success: function(responseXml) {
92 | utils.hideMessage();
93 | var xml = $(responseXml);
94 | var nextUrl = utils.format('{0}#state=postupload&playlist={1}', utils.currentUrlWithoutParams(), globals.hashParams.playlist);
95 | var submissionUrl = utils.format('{0}?nexturl={1}', xml.find('url').text(), encodeURIComponent(nextUrl));
96 | var token = xml.find('token').text();
97 |
98 | $('#upload-form').attr('action', submissionUrl);
99 | $('').attr({
100 | type: 'hidden',
101 | name: 'token',
102 | value: token
103 | }).appendTo('#upload-form');
104 |
105 | $('#upload-form').submit();
106 | },
107 | error: function(jqXHR) {
108 | utils.showMessage('Metadata submission failed: ' + jqXHR.responseText);
109 | $('#upload').removeAttr('disabled');
110 | $('#upload').val('Upload');
111 | }
112 | });
113 | });
114 |
115 | $('[required]').change(function() {
116 | var disabled = false;
117 |
118 | $.each($('[required]:visible'), function() {
119 | if (!$(this).val()) {
120 | disabled = true;
121 | }
122 | });
123 |
124 | if (disabled) {
125 | $('#upload').attr('disabled', true);
126 | } else {
127 | $('#upload').removeAttr('disabled');
128 | }
129 | });
130 | }
131 | };
132 | });
--------------------------------------------------------------------------------
/static/js/ytdl/panels/webcam.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery', '../utils', '../constants', '../globals', '../config'], function($, utils, constants, globals, config) {
18 | var webcam = {
19 | needsPlaylist: true,
20 | init: function() {
21 | if (typeof(YT) == 'undefined' || typeof(YT.UploadWidget) == 'undefined') {
22 | window.onYouTubeIframeAPIReady = function() {
23 | webcam.loadUploadWidget();
24 | };
25 |
26 | $.getScript('//www.youtube.com/iframe_api');
27 | } else {
28 | webcam.loadUploadWidget();
29 | }
30 | },
31 |
32 | loadUploadWidget: function() {
33 | new YT.UploadWidget('webcam-widget', {
34 | webcamOnly: true,
35 | events: {
36 | onApiReady: function(event) {
37 | event.target.setVideoTitle(config.VIDEO_TITLE || constants.WEBCAM_VIDEO_TITLE);
38 | event.target.setVideoDescription(config.VIDEO_DESCRIPTION || constants.WEBCAM_VIDEO_DESCRIPTION);
39 | event.target.setVideoKeywords([utils.generateKeywordFromPlaylistId(globals.hashParams.playlist)]);
40 | },
41 | onUploadSuccess: function(event) {
42 | utils.showMessage('Your webcam submission was received.');
43 |
44 | window._gaq.push(['_trackEvent', 'Submission', 'Webcam', 'Success']);
45 | },
46 | onStateChange: function(event) {
47 | if (event.data.state == YT.UploadWidgetState.ERROR) {
48 | window._gaq.push(['_trackEvent', 'Submission', 'Webcam', 'Error']);
49 | }
50 | }
51 | }
52 | });
53 | }
54 | };
55 |
56 | return webcam;
57 | });
--------------------------------------------------------------------------------
/static/js/ytdl/player.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define(['jquery'], function($) {
18 | var player = {
19 | playVideo: function(container, videoId) {
20 | if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
21 | window.onYouTubeIframeAPIReady = function() {
22 | player.loadPlayer(container, videoId);
23 | };
24 |
25 | $.getScript('//www.youtube.com/iframe_api');
26 | } else {
27 | player.loadPlayer(container, videoId);
28 | }
29 | },
30 |
31 | loadPlayer: function(container, videoId) {
32 | new YT.Player(container, {
33 | videoId: videoId,
34 | width: 356,
35 | height: 200,
36 | playerVars: {
37 | autoplay: 1,
38 | controls: 0,
39 | modestbranding: 1,
40 | rel: 0,
41 | showInfo: 0
42 | }
43 | });
44 | }
45 | };
46 |
47 | return player;
48 | });
--------------------------------------------------------------------------------
/static/js/ytdl/utils.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Google Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | define([
18 | 'jquery',
19 | './constants',
20 | './globals',
21 | './config',
22 | 'third-party/jquery.parseparams'
23 | ], function($, constants, globals, config) {
24 | var utils = {
25 | format: function() {
26 | var replacements = Array.prototype.slice.call(arguments);
27 | var originalString = replacements.shift();
28 | if ($.isPlainObject(replacements[0])) {
29 | replacements = replacements[0];
30 | }
31 | if (originalString) {
32 | return originalString.replace(/{(\w+)}/g, function(match, i) {
33 | return typeof replacements[i] != 'undefined' ? replacements[i] : '';
34 | });
35 | } else {
36 | return '';
37 | }
38 | },
39 |
40 | generateYouTubeApiHeaders: function(extraHeaders) {
41 | var headers = extraHeaders || {};
42 | headers['Authorization'] = utils.format('{0} {1}', constants.OAUTH2_TOKEN_TYPE, gapi.auth.getToken().access_token);
43 | headers['GData-Version'] = 2;
44 | headers['X-GData-Key'] = utils.format('key={0}', config.DEVELOPER_KEY);
45 | headers['X-GData-Client'] = utils.format('{0}-{1}', constants.DEFAULT_KEYWORD, globals.parsedUrl.authority);
46 | return headers;
47 | },
48 |
49 | escapeXmlEntities: function(input) {
50 | if (input) {
51 | return input.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
52 | } else {
53 | return '';
54 | }
55 | },
56 |
57 | showMessage: function(message) {
58 | $('#message').text(message);
59 | $('#message').show();
60 | },
61 |
62 | showHtmlMessage: function(message) {
63 | $('#message').html(message);
64 | $('#message').show();
65 | },
66 |
67 | hideMessage: function() {
68 | $('#message').hide();
69 | $('#message').text();
70 | },
71 |
72 | animateModeration: function(target, destination) {
73 | var currentPosition = target.position();
74 | var destinationPosition = destination.position();
75 | var originalHeight = target.height();
76 | var originalWidth = target.width();
77 |
78 | target.css({
79 | position: 'absolute',
80 | left: currentPosition.left,
81 | top: currentPosition.top
82 | });
83 |
84 | target.animate({
85 | opacity: 0.5,
86 | left: destinationPosition.left,
87 | top: destinationPosition.top,
88 | height: originalHeight * 0.1,
89 | width: originalWidth * 0.1
90 | }, 'slow', function() {
91 | target.hide();
92 | });
93 | },
94 |
95 | updateHashParams: function() {
96 | globals.hashParams = $.parseParams(decodeURIComponent(window.location.hash.replace('#', '')));
97 | },
98 |
99 | generateKeywordFromPlaylistId: function(playlistId) {
100 | playlistId = playlistId || '';
101 |
102 | if (playlistId.indexOf('PL') == 0) {
103 | playlistId = playlistId.substring(2);
104 | }
105 |
106 | var keyword = utils.format('{0}{1}', constants.DEFAULT_KEYWORD, playlistId);
107 | keyword = keyword.replace(/\W/g, '');
108 | if (keyword.length > constants.MAX_KEYWORD_LENGTH) {
109 | keyword = keyword.substring(0, constants.MAX_KEYWORD_LENGTH);
110 | }
111 | return keyword;
112 | },
113 |
114 | formatDuration: function(durationInSeconds) {
115 | var minutes = parseInt(durationInSeconds / 60);
116 | var seconds = durationInSeconds - (minutes * 60);
117 | if (seconds < 10) {
118 | seconds = utils.format('0{0}', seconds);
119 | }
120 | return utils.format('{0}:{1}', minutes, seconds);
121 | },
122 |
123 | redirect: function(panel, playlist) {
124 | var hash = utils.format('state={0}&playlist={1}', panel, playlist || globals.hashParams.playlist);
125 | window.location.hash = hash;
126 | if (panel == globals.hashParams.state) {
127 | $(window).trigger('hashchange');
128 | }
129 | },
130 |
131 | getFeed: function(options) {
132 | var startIndex = options.startIndex || 1;
133 | var maxResults = options.maxResults || 1000;
134 | var results = options.results || [];
135 |
136 | var url = options.url;
137 | if (url.indexOf('?') == -1) {
138 | url += '?';
139 | } else {
140 | url += '&';
141 | }
142 | url = utils.format('{0}max-results={1}&alt=json&start-index={2}', url, constants.PAGE_SIZE, startIndex);
143 |
144 | if (options.cacheMinutes && results.length == 0) {
145 | results = lscache.get(options.url);
146 | if (results == null) {
147 | results = [];
148 | } else {
149 | (options.callback)(results);
150 | return;
151 | }
152 | }
153 |
154 | $.ajax({
155 | dataType: 'json',
156 | type: 'GET',
157 | url: url,
158 | headers: utils.generateYouTubeApiHeaders(),
159 | success: function(responseJson) {
160 | if ('entry' in responseJson['feed']) {
161 | $.merge(results, responseJson['feed']['entry']);
162 |
163 | if (results.length < maxResults && responseJson['feed']['entry'].length == constants.PAGE_SIZE) {
164 | utils.getFeed({
165 | cacheMinutes: options.cacheMinutes,
166 | callback: options.callback,
167 | maxResults: maxResults,
168 | results: results,
169 | startIndex: startIndex + constants.PAGE_SIZE,
170 | url: options.url
171 | });
172 | } else {
173 | if (options.cacheMinutes) {
174 | lscache.set(options.url, results, options.cacheMinutes);
175 | }
176 | (options.callback)(results);
177 | }
178 | } else {
179 | if (options.cacheMinutes) {
180 | lscache.set(options.url, results, options.cacheMinutes);
181 | }
182 | (options.callback)(results);
183 | }
184 | },
185 | error: function(jqXHR) {
186 | if (results.length > 0) {
187 | (options.callback)(results);
188 | } else {
189 | utils.showMessage('Your request could not be completed: ' + jqXHR.responseText);
190 | }
191 | }
192 | });
193 | },
194 |
195 | getThumbnailUrlFromEntry: function(entry, thumbnailName) {
196 | var thumbnailUrl = constants.NO_THUMBNAIL_URL;
197 |
198 | if ('media$group' in entry && 'media$thumbnail' in entry['media$group']) {
199 | $.each(entry['media$group']['media$thumbnail'], function(i, thumbnailEntry) {
200 | if (thumbnailEntry['yt$name'] == thumbnailName) {
201 | thumbnailUrl = thumbnailEntry['url'];
202 | }
203 | });
204 | }
205 |
206 | return thumbnailUrl;
207 | },
208 |
209 | currentUrlWithoutParams: function() {
210 | return utils.format('{0}://{1}{2}', globals.parsedUrl.protocol, globals.parsedUrl.authority, globals.parsedUrl.path);
211 | },
212 |
213 | itemsInResponse: function(response) {
214 | return ('items' in response && response.items.length > 0);
215 | },
216 |
217 | getErrorResponseString: function(response) {
218 | var errorString = 'Unknown error.';
219 |
220 | if ('error' in response && 'data' in response.error && response.error.data.length > 0) {
221 | var error = response.error.data[0];
222 | errorString = utils.format('{0}: {1}', error.reason || 'Error', error.message);
223 | if (error.location) {
224 | errorString += utils.format(' ({0})', error.location);
225 | }
226 | }
227 |
228 | return errorString;
229 | },
230 |
231 | getAllItems: function(service, params, callback, items) {
232 | if (!items) {
233 | items = [];
234 | }
235 | params['maxResults'] = constants.PAGE_SIZE;
236 |
237 | var request = gapi.client.request({
238 | path: utils.format('/{0}/{1}/{2}', constants.YOUTUBE_API_SERVICE_NAME, constants.YOUTUBE_API_VERSION, service),
239 | method: 'GET',
240 | params: params
241 | });
242 | request.execute(function(response) {
243 | if (utils.itemsInResponse(response)) {
244 | items = items.concat(response.items);
245 | } else if ('error' in response) {
246 | utils.showMessage('Request failed. ' + utils.getErrorResponseString(response));
247 | }
248 |
249 | if ('nextPageToken' in response && items.length < constants.MAX_ITEMS_TO_RETRIEVE) {
250 | params['pageToken'] = response.nextPageToken;
251 | utils.getAllItems(service, params, callback, items);
252 | } else {
253 | callback(items);
254 | }
255 | });
256 | },
257 |
258 | getInfoForVideoIds: function(videoIds, callback, videos) {
259 | if (!videos) {
260 | videos = [];
261 | }
262 |
263 | var pageOfVideoIds = videoIds.splice(0, constants.PAGE_SIZE);
264 | if (pageOfVideoIds.length > 0) {
265 | var request = gapi.client[constants.YOUTUBE_API_SERVICE_NAME].videos.list({
266 | id: pageOfVideoIds.join(','),
267 | part: 'snippet,contentDetails,status'
268 | });
269 | request.execute(function(response) {
270 | if (utils.itemsInResponse(response)) {
271 | videos = videos.concat(response.items);
272 | utils.getInfoForVideoIds(videoIds, callback, videos);
273 | } else {
274 | utils.showMessage('Unable to retrieve info about videos. ' + utils.getErrorResponseString(response));
275 | callback(videos);
276 | }
277 | });
278 | } else {
279 | callback(videos);
280 | }
281 | },
282 |
283 | formatPeriodOfTime: function(duration) {
284 | var matches = duration.match(/PT(?:(\d+)H)?(?:(\d+)M)?(\d+)S/);
285 |
286 | var hours = parseInt(matches[1]) || 0;
287 | var minutes = parseInt(matches[2]) || 0;
288 | minutes += hours * 60;
289 | var seconds = parseInt(matches[3]) || 0;
290 | if (seconds < 10) {
291 | seconds = '0' + seconds;
292 | }
293 |
294 | return utils.format('{0}:{1}', minutes, seconds);
295 | },
296 |
297 | getEditLinkUrlFromEntry: function(entry) {
298 | var editLinkUrl = '';
299 | $.each(entry['link'], function(i, link) {
300 | if (link['rel'] == 'edit') {
301 | editLinkUrl = link['href'];
302 | }
303 | });
304 | return editLinkUrl;
305 | },
306 |
307 | getPlaylistIdFromEditUrl: function(editUrl) {
308 | var matches = /playlists\/([^/]+)\//.exec(editUrl);
309 | if (matches.length > 1) {
310 | return matches[1];
311 | }
312 |
313 | return '';
314 | },
315 |
316 | getPlaylists: function(callback) {
317 | utils.getAllItems('playlists', {
318 | part: 'id,snippet',
319 | mine: true
320 | }, function(playlists) {
321 | var entriesToReturn = [];
322 | $.each(playlists, function() {
323 | if (this.snippet.title == constants.REJECTED_VIDEOS_PLAYLIST) {
324 | globals.rejectedPlaylistId = this.id;
325 | } else {
326 | entriesToReturn.push(this);
327 | }
328 | });
329 |
330 | if (globals.rejectedPlaylistId) {
331 | callback(entriesToReturn);
332 | } else {
333 | utils.addPlaylist(constants.REJECTED_VIDEOS_PLAYLIST, true, function(playlistId) {
334 | globals.rejectedPlaylistId = playlistId;
335 |
336 | callback(entriesToReturn);
337 | });
338 | }
339 | });
340 | },
341 |
342 | addPlaylist: function(name, isPrivate, callback) {
343 | lscache.remove(utils.format('{0}/feeds/api/users/default/playlists', constants.GDATA_SERVER));
344 |
345 | var request = gapi.client.youtube.playlists.insert({
346 | part: 'snippet,status',
347 | resource: {
348 | snippet: {
349 | title: name
350 | },
351 | status: {
352 | privacyStatus: isPrivate ? 'private' : 'public'
353 | }
354 | }
355 | });
356 | request.execute(function(response) {
357 | if ('error' in response) {
358 | utils.showMessage('Could not create playlist. ' + utils.getErrorResponseString(response));
359 | } else {
360 | callback(response.id);
361 | }
362 | });
363 |
364 | window._gaq.push(['_trackEvent', 'Admin', 'Create Playlist']);
365 | },
366 |
367 | getMetadataFromEntry: function(entry) {
368 | var durationInSeconds = 0;
369 | if ('yt$duration' in entry['media$group']) {
370 | durationInSeconds = entry['media$group']['yt$duration']['seconds'];
371 | }
372 |
373 | return {
374 | thumbnailUrl: utils.getThumbnailUrlFromEntry(entry, 'hqdefault'),
375 | uploadedDate: new Date(entry['published']['$t']).toDateString(),
376 | duration: utils.formatDuration(durationInSeconds),
377 | uploader: entry['media$group']['media$credit'][0]['yt$display'],
378 | videoId: entry['media$group']['yt$videoid']['$t'],
379 | title: entry['title']['$t']
380 | };
381 | },
382 |
383 | addVideoToPlaylist: function(playlistId, videoId) {
384 | lscache.remove(utils.format('{0}/feeds/api/users/default/playlists', constants.GDATA_SERVER));
385 | lscache.remove(playlistId);
386 |
387 | var request = gapi.client.youtube.playlistItems.insert({
388 | part: 'snippet',
389 | resource: {
390 | snippet: {
391 | playlistId: playlistId,
392 | resourceId: {
393 | kind: 'youtube#video',
394 | videoId: videoId
395 | },
396 | position: 0
397 | }
398 | }
399 | });
400 | request.execute(function(response) {
401 | if ('error' in response) {
402 | utils.showMessage('Could not add video playlist. ' + utils.getErrorResponseString(response));
403 | } else {
404 | utils.showMessage('Success!');
405 | }
406 | });
407 | },
408 |
409 | removeVideoFromPlaylist: function(editUrl) {
410 | var playlistId = utils.getPlaylistIdFromEditUrl(editUrl);
411 | if (playlistId) {
412 | lscache.remove(playlistId);
413 | }
414 | lscache.remove(utils.format('{0}/feeds/api/users/default/playlists', constants.GDATA_SERVER));
415 |
416 | $.ajax({
417 | type: 'DELETE',
418 | url: editUrl,
419 | headers: utils.generateYouTubeApiHeaders(),
420 | success: function() {
421 | utils.showMessage('Success!');
422 | },
423 | error: function(jqXHR) {
424 | utils.showMessage(utils.format('Could not remove video from playlist: {0}', jqXHR.responseText));
425 | }
426 | });
427 | },
428 |
429 | getStateOfSubmissions: function(callback) {
430 | var state = lscache.get(globals.hashParams.playlist);
431 | if (state) {
432 | callback(state);
433 | return;
434 | }
435 |
436 | if (!globals.rejectedPlaylistId) {
437 | callback();
438 | return;
439 | }
440 |
441 | utils.getFeed({
442 | url: utils.format('{0}/feeds/api/playlists/{1}', constants.GDATA_SERVER, globals.hashParams.playlist),
443 | callback: function(playlistEntries) {
444 | var videoIdToPlaylistEntryId = {};
445 | var videoIdToMetadata = {};
446 | var approvedIds = [];
447 |
448 | $.each(playlistEntries, function() {
449 | var approvedId = this['media$group']['yt$videoid']['$t'];
450 | approvedIds.push(approvedId);
451 | videoIdToPlaylistEntryId[approvedId] = utils.getEditLinkUrlFromEntry(this);
452 | videoIdToMetadata[approvedId] = utils.getMetadataFromEntry(this);
453 | });
454 |
455 | utils.getFeed({
456 | url: utils.format('{0}/feeds/api/playlists/{1}', constants.GDATA_SERVER, globals.rejectedPlaylistId),
457 | callback: function(rejectedPlaylistEntries) {
458 | var allRejectedIds = [];
459 | var rejectedIds = [];
460 |
461 | $.each(rejectedPlaylistEntries, function() {
462 | var rejectedId = this['media$group']['yt$videoid']['$t'];
463 | if (!(rejectedId in videoIdToPlaylistEntryId)) {
464 | allRejectedIds.push(rejectedId);
465 | videoIdToPlaylistEntryId[rejectedId] = utils.getEditLinkUrlFromEntry(this);
466 | videoIdToMetadata[rejectedId] = utils.getMetadataFromEntry(this);
467 | }
468 | });
469 |
470 | var keyword = utils.generateKeywordFromPlaylistId(globals.hashParams.playlist);
471 | utils.getFeed({
472 | url: utils.format('{0}/feeds/api/videos?category=%7Bhttp%3A%2F%2Fgdata.youtube.com%2Fschemas%2F2007%2Fkeywords.cat%7D{1}', constants.GDATA_SERVER, keyword),
473 | callback: function(searchEntries) {
474 | var pendingIds = [];
475 | $.each(searchEntries, function() {
476 | var searchId = this['media$group']['yt$videoid']['$t'];
477 | if (!(searchId in videoIdToPlaylistEntryId)) {
478 | pendingIds.push(searchId);
479 | videoIdToMetadata[searchId] = utils.getMetadataFromEntry(this);
480 | } else if ($.inArray(searchId, allRejectedIds) != -1) {
481 | rejectedIds.push(searchId);
482 | }
483 | });
484 |
485 | state = {
486 | videoIdToPlaylistEntryId: videoIdToPlaylistEntryId,
487 | videoIdToMetadata: videoIdToMetadata,
488 | pendingIds: pendingIds,
489 | approvedIds: approvedIds,
490 | rejectedIds: rejectedIds
491 | };
492 |
493 | lscache.set(globals.hashParams.playlist, state, constants.STATE_CACHE_MINUTES);
494 | callback(state);
495 | }
496 | });
497 | }
498 | });
499 | }
500 | });
501 | }
502 | };
503 |
504 | return utils;
505 | });
--------------------------------------------------------------------------------