Coverage for webapp/snapcraft/views.py: 46%
84 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-15 22:43 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-15 22:43 +0000
1import flask
3from webapp.config import DEFAULT_ICON_URL
4from webapp.snapcraft import logic
7def snapcraft_blueprint():
8 snapcraft = flask.Blueprint("snapcraft", __name__)
10 @snapcraft.route("/")
11 def homepage():
12 nps = flask.request.args.get("nps")
14 livestream = logic.get_livestreams()
16 return flask.render_template(
17 "index.html", nps=nps, livestream=livestream
18 )
20 @snapcraft.route("/account.json")
21 def get_account_json():
22 """
23 A JSON endpoint to request login status
24 """
25 try:
26 publisher = None
28 if "publisher" in flask.session:
29 publisher = flask.session["publisher"]
31 response = {"publisher": publisher}
32 response = flask.make_response(response)
34 # Unset the last_login_method cookie to avoid forcing
35 response.set_cookie("last_login_method", "", expires=0)
37 response.headers["Cache-Control"] = "no-store"
39 return response
40 except Exception:
41 response = {"error": "Error fetching account information"}
42 response = flask.make_response(response)
43 response.headers["Cache-Control"] = "no-store"
44 return response, 502
46 @snapcraft.route("/iot")
47 def iot():
48 status_code = 200
50 icon_host = "https://dashboard.snapcraft.io/site_media/appmedia"
52 devices = [
53 {
54 "package_name": "ubuntu-frame-osk",
55 "icon_url": "/".join([icon_host, "2023/03/icon_2_Frame.png"]),
56 "title": "Ubuntu Frame",
57 "developer_name": "Canonical",
58 "developer_link": "/publisher/canonical",
59 "developer_validation": "verified",
60 },
61 {
62 "package_name": "mir-kiosk",
63 "icon_url": "/".join(
64 [icon_host, "2021/06/mir-sqr-stacked-orng.png"]
65 ),
66 "title": "mir-kiosk",
67 "developer_name": "Canonical",
68 "developer_link": "/publisher/canonical",
69 "developer_validation": "verified",
70 },
71 {
72 "package_name": "edgexfoundry",
73 "icon_url": "/".join([icon_host, "2018/12/icon_Hx6IyH0.png"]),
74 "title": "Edgexfoundry",
75 "developer_name": "Canonical",
76 "developer_link": "/publisher/canonical",
77 "developer_validation": "verified",
78 },
79 {
80 "package_name": "node-red",
81 "icon_url": "/".join([icon_host, "2017/01/nr-hex_1.png"]),
82 "title": "Node-Red",
83 "developer_name": "Node-RED-Team (noderedteam)",
84 "developer_link": "/publisher/noderedteam",
85 "developer_validation": "verified",
86 },
87 {
88 "package_name": "bluez",
89 "icon_url": "/".join(
90 [icon_host, "2020/05/bluez-logo-2.jpg.png"]
91 ),
92 "title": "bluez",
93 "developer_name": "Canonical",
94 "developer_link": "/publisher/canonical",
95 "developer_validation": "verified",
96 },
97 {
98 "package_name": "zwave-js-ui",
99 "icon_url": "/".join(
100 [icon_host, "2022/10/app_logo-svg_2.svg.png"]
101 ),
102 "title": "Zwave JS UI",
103 "developer_name": "Giaever.online (giaever-online)",
104 "developer_link": "/publisher/giaever-online",
105 },
106 {
107 "package_name": "ubports-installer",
108 "icon_url": "/".join(
109 [icon_host, "2017/09/256x256_h3aYso1.png"]
110 ),
111 "title": "ubports-installer",
112 "developer_name": "UBports",
113 "developer_link": "/publisher/ubports",
114 },
115 {
116 "package_name": "librepcb",
117 "icon_url": "/".join([icon_host, "2022/10/librepcb.png"]),
118 "title": "LibrePCB",
119 "developer_name": "librepcb",
120 "developer_link": "/publisher/librepcb",
121 "developer_validation": "verified",
122 },
123 {
124 "package_name": "ammp-edge",
125 "icon_url": "/".join(
126 [icon_host, "2020/12/glyph-rounder-square-180px.png"]
127 ),
128 "title": "ammp-edge",
129 "developer_name": "AMMP Technologies (ammp)",
130 "developer_link": "/publisher/ammp",
131 },
132 {
133 "package_name": "pi-bluetooth",
134 "icon_url": DEFAULT_ICON_URL,
135 "title": "pi-bluetooth",
136 "developer_name": "Dave Jones (waveform)",
137 "developer_link": "/publisher/waveform",
138 },
139 ]
141 robotics = [
142 {
143 "package_name": "arduino",
144 "icon_url": "/".join([icon_host, "2020/02/icon_s4HbwJl.png"]),
145 "title": "Arduino IDE",
146 "developer_name": "Snapcrafters",
147 "developer_link": "/publisher/snapcrafters",
148 "developer_validation": "starred",
149 },
150 {
151 "package_name": "rosbot-xl",
152 "icon_url": "/".join([icon_host, "2024/06/rosbot-xl.png"]),
153 "title": "ROSbot XL",
154 "developer_name": "Husarion",
155 "developer_link": "/publisher/husarion",
156 "developer_validation": "verified",
157 },
158 {
159 "package_name": "rosbot-xl-teleop",
160 "icon_url": "/".join(
161 [icon_host, "2023/10/popr512x512px_rosbot_xl_teleop.png"]
162 ),
163 "title": "ROSbot XL: teleop",
164 "developer_name": "Husarion",
165 "developer_link": "/publisher/husarion",
166 "developer_validation": "verified",
167 },
168 {
169 "package_name": "webots",
170 "icon_url": "/".join([icon_host, "2019/08/webots.png"]),
171 "title": "Webots",
172 "developer_name": "Cyberbotics",
173 "developer_link": "/publisher/cyberbotics",
174 },
175 {
176 "package_name": "gazebo",
177 "icon_url": "/".join([icon_host, "2022/05/icon.svg.png"]),
178 "title": "gazebo",
179 "developer_name": (
180 "Ubuntu Robotics Community (ubuntu-robotics-community)"
181 ),
182 "developer_link": "/publisher/ubuntu-robotics-community",
183 "developer_validation": "verified",
184 },
185 {
186 "package_name": "ros2-cli",
187 "icon_url": "/".join(
188 [icon_host, "2023/02/ros2-cli_icon_1.png"]
189 ),
190 "title": "ros2-cli",
191 "developer_name": (
192 "Ubuntu Robotics Community (ubuntu-robotics-community)"
193 ),
194 "developer_link": "/publisher/ubuntu-robotics-community",
195 "developer_validation": "verified",
196 },
197 {
198 "package_name": "vulcanexus-router",
199 "icon_url": "/".join([icon_host, "2023/05/V-DDSRouter.png"]),
200 "title": "Vulcanexus Router",
201 "developer_name": "eProsima",
202 "developer_link": "/publisher/eprosima",
203 },
204 {
205 "package_name": "bow-webots",
206 "icon_url": DEFAULT_ICON_URL,
207 "title": "BOW Webots",
208 "developer_name": "Daniel Camilleri (bow-robotics)",
209 "developer_link": "/publisher/bow-robotics",
210 },
211 {
212 "package_name": "foxglove-studio",
213 "icon_url": "/".join([icon_host, "2022/07/fs-icon.svg.png"]),
214 "title": "foxglove-studio",
215 "developer_name": "Roman Shtylman (roman-foxglove)",
216 "developer_link": "/publisher/roman-foxglove",
217 },
218 {
219 "package_name": "husarion-ouster",
220 "icon_url": "/".join(
221 [icon_host, "2023/10/husarion-ouster.png"]
222 ),
223 "title": "husarion-ouster",
224 "developer_name": "Husarion",
225 "developer_link": "/publisher/husarion",
226 "developer_validation": "verified",
227 },
228 ]
230 smart_home = [
231 {
232 "package_name": "openhab",
233 "icon_url": "/".join([icon_host, "2017/11/favicon.png"]),
234 "title": "openhab",
235 "developer_name": "openHAB Foundation e.V. (openhab)",
236 "developer_link": "/publisher/openhab",
237 },
238 {
239 "package_name": "homebridge",
240 "icon_url": "/".join([icon_host, "2018/10/Logo2x.png"]),
241 "title": "homebridge",
242 "developer_name": "Ondrej Kubik (ondra)",
243 },
244 {
245 "package_name": "home-assistant-snap",
246 "icon_url": "/".join(
247 [icon_host, "2020/07/favicon-192x192.png"]
248 ),
249 "title": "Home Assistant",
250 "developer_name": "Giaever.online (giaever-online)",
251 "developer_link": "/publisher/giaever-online",
252 },
253 {
254 "package_name": "security-bear",
255 "icon_url": "/".join(
256 [icon_host, "2020/11/security-bear_Logo.png"]
257 ),
258 "title": "security-bear",
259 "developer_name": "CyBear Jinni (cybearjinni)",
260 "developer_link": "/publisher/cybearjinni",
261 },
262 {
263 "package_name": "chip-tool",
264 "icon_url": "/".join([icon_host, "2023/01/1F3E0_color.png"]),
265 "title": "chip-tool",
266 "developer_name": "Canonical IoT Labs (canonical-iot-labs)",
267 "developer_link": "/publisher/canonical-iot-labs",
268 },
269 {
270 "package_name": "openthread-border-router",
271 "icon_url": "/".join(
272 [icon_host, "2023/09/ThreadLogo-stort-1.png"]
273 ),
274 "title": "openthread-border-router",
275 "developer_name": "Canonical IoT Labs (canonical-iot-labs)",
276 "developer_link": "/publisher/canonical-iot-labs",
277 },
278 {
279 "package_name": "matter-bridge-tapo-lighting",
280 "icon_url": "/".join(
281 [icon_host, "2023/01/1F3E0_color_8tMXOjP.png"]
282 ),
283 "title": "matter-bridge-tapo-lighting",
284 "developer_name": "Canonical IoT Labs (canonical-iot-labs)",
285 "developer_link": "/publisher/canonical-iot-labs",
286 },
287 {
288 "package_name": "matter-pi-gpio-commander",
289 "icon_url": "/".join([icon_host, "2023/03/E1C7_color.png"]),
290 "title": "matter-pi-gpio-commander",
291 "developer_name": "Canonical IoT Labs (canonical-iot-labs)",
292 "developer_link": "/publisher/canonical-iot-labs",
293 },
294 ]
296 networking = [
297 {
298 "package_name": "mosquitto",
299 "icon_url": "/".join(
300 [icon_host, "2018/08/mosquitto-logo-only.svg.png"]
301 ),
302 "title": "mosquitto",
303 "developer_name": "Mosquitto Team (mosquitto)",
304 "developer_link": "/publisher/mosquitto",
305 "developer_validation": "verified",
306 },
307 {
308 "package_name": "domotzpro-agent-publicstore",
309 "icon_url": "/".join(
310 [icon_host, "2019/03/new_domotz_icon.png"]
311 ),
312 "title": "Domotz Pro Agent",
313 "developer_name": "Domotz (domotzpublicstore)",
314 "developer_link": "/publisher/domotzpublicstore",
315 "developer_validation": "verified",
316 },
317 {
318 "package_name": "adguard-home",
319 "icon_url": "/".join([icon_host, "2020/04/256.png"]),
320 "title": "AdGuard Home",
321 "developer_name": "AdGuard (ameshkov)",
322 "developer_link": "/publisher/ameshkov",
323 "developer_validation": "verified",
324 },
325 {
326 "package_name": "flexran",
327 "icon_url": "/".join([icon_host, "2018/04/m5g-flexran.png"]),
328 "title": "flexran",
329 "developer_name": "Mosaic 5G (mosaic-5g)",
330 "developer_link": "/publisher/mosaic-5g",
331 },
332 {
333 "package_name": "modem-manager",
334 "icon_url": "/".join([icon_host, "2020/05/mm-logo.png"]),
335 "title": "modem-manager",
336 "developer_name": "Canonical",
337 "developer_link": "/publisher/canonical",
338 "developer_validation": "verified",
339 },
340 {
341 "package_name": "snap-store-proxy",
342 "icon_url": "/".join(
343 [icon_host, "2018/09/Snapcraft_Proxy_Aubergine-256.png"]
344 ),
345 "title": "snap-store-proxy",
346 "developer_name": "Canonical",
347 "developer_link": "/publisher/canonical",
348 "developer_validation": "verified",
349 },
350 ]
352 board_images = [
353 {
354 "package_name": "pc",
355 "icon_url": "/".join([icon_host, "2016/07/icon_30.png"]),
356 "title": "PC",
357 "developer_name": "Canonical",
358 "developer_link": "/publisher/canonical",
359 "developer_validation": "verified",
360 },
361 {
362 "package_name": "rpi-imager",
363 "icon_url": "/".join([icon_host, "2020/03/rpi-imager.png"]),
364 "title": "rpi-imager",
365 "developer_name": "Dave Jones (waveform)",
366 "developer_link": "/publisher/waveform",
367 },
368 {
369 "package_name": "pi-desktop",
370 "icon_url": DEFAULT_ICON_URL,
371 "title": "pi-desktop",
372 "developer_name": "Canonical",
373 "developer_link": "/publisher/canonical",
374 "develper_validation": "verified",
375 },
376 {
377 "package_name": "pi",
378 "icon_url": DEFAULT_ICON_URL,
379 "title": "pi",
380 "developer_name": "Canonical",
381 "developer_link": "/publisher/canonical",
382 "developer_validation": "verified",
383 },
384 {
385 "package_name": "pi2",
386 "icon_url": "/".join([icon_host, "2015/04/berry.jpg.png"]),
387 "title": "pi2",
388 "developer_name": "Canonical",
389 "developer_link": "/publisher/canonical",
390 "developer_validation": "verified",
391 },
392 {
393 "package_name": "pi3",
394 "icon_url": DEFAULT_ICON_URL,
395 "title": "pi3",
396 "developer_name": "Canonical",
397 "developer_link": "/publisher/canonical",
398 "developer_validation": "verified",
399 },
400 ]
402 context = {
403 "devices": devices,
404 "robotics": robotics,
405 "smart_home": smart_home,
406 "networking": networking,
407 "board_images": board_images,
408 }
410 return (
411 flask.render_template("store/categories/iot.html", **context),
412 status_code,
413 )
415 @snapcraft.route("/about")
416 def about():
417 return flask.render_template("about/index.html")
419 @snapcraft.route("/about/publish")
420 def about_publish():
421 return flask.render_template("about/publish.html")
423 @snapcraft.route("/about/listing")
424 def about_listing():
425 return flask.render_template("about/listing.html")
427 @snapcraft.route("/about/release")
428 def about_release():
429 return flask.render_template("about/release.html")
431 @snapcraft.route("/about/publicise")
432 def about_publicise():
433 return flask.render_template("about/publicise.html")
435 @snapcraft.route("/about/contact-us")
436 def about_contact():
437 return flask.render_template("contact-us.html")
439 @snapcraft.route("/about/thank-you")
440 def about_thankyou():
441 return flask.render_template("thank-you.html")
443 @snapcraft.route("/community")
444 def community_redirect():
445 return flask.redirect("/")
447 @snapcraft.route("/create")
448 def create_redirect():
449 return flask.redirect("https://docs.snapcraft.io/build-snaps")
451 @snapcraft.route("/build")
452 def build():
453 status_code = 200
455 return flask.render_template("snapcraft/build.html"), status_code
457 @snapcraft.route("/sitemap.xml")
458 def sitemap():
459 xml_sitemap = flask.render_template(
460 "sitemap/sitemap-index.xml",
461 base_url="https://snapcraft.io",
462 )
463 response = flask.make_response(xml_sitemap)
464 response.headers["Content-Type"] = "application/xml"
466 return response
468 @snapcraft.route("/sitemap-links.xml")
469 def sitemap_links():
470 base_url = "https://snapcraft.io"
471 links = [
472 {"url": f"{base_url}/about"},
473 {"url": f"{base_url}/about/publish"},
474 {"url": f"{base_url}/about/listing"},
475 {"url": f"{base_url}/about/release"},
476 {"url": f"{base_url}/about/publicise"},
477 {"url": f"{base_url}/iot"},
478 ]
480 xml_sitemap = flask.render_template(
481 "sitemap/sitemap.xml",
482 base_url="https://snapcraft.io",
483 links=links,
484 )
485 response = flask.make_response(xml_sitemap)
486 response.headers["Content-Type"] = "application/xml"
487 response.headers["Cache-Control"] = "public, max-age=43200"
489 return response
491 return snapcraft