Lateo.net - Flux RSS en pagaille (pour en ajouter : @ moi)

🔒
❌ À propos de FreshRSS
Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
À partir d’avant-hierInformatique & geek

It’s cutting calories—not intermittent fasting—that drops weight, study suggests

Par : Beth Mole
It’s cutting calories—not intermittent fasting—that drops weight, study suggests

Enlarge (credit: Getty | David Jennings)

Intermittent fasting, aka time-restricted eating, can help people lose weight—but the reason why may not be complicated hypotheses about changes from fasting metabolism or diurnal circadian rhythms. It may just be because restricting eating time means people eat fewer calories overall.

In a randomized-controlled trial, people who followed a time-restricted diet lost about the same amount of weight as people who ate the same diet without the time restriction, according to a study published Friday in Annals of Internal Medicine.

The finding offers a possible answer to a long-standing question for time-restricted eating (TRE) research, which has been consumed by small feeding studies of 15 people or fewer, with mixed results and imperfect designs.

Read 8 remaining paragraphs | Comments

Loi italienne : restreindre le partage en ligne de la vie des enfants

L'Italie envisage de limiter le partage en ligne de la vie des enfants à travers une nouvelle législation, inspirée par des préoccupations croissantes concernant la vie privée des jeunes sur les réseaux sociaux....

SUPIR – L’IA qui restaure vos photos comme jamais

Par : Korben

SUPIR (Scaling-UP Image Restoration) est une avancée majeure dans le domaine de la restauration d’images intelligente et réaliste. En s’appuyant sur des techniques multi-modales et des générateurs préentraînés avancés, SUPIR repousse les limites de ce qui est possible en termes de qualité et de contrôle de la restauration en combinant ce qui se fait de mieux en ce moment en IA.

Au cœur de SUPIR se trouve un modèle génératif que vous connaissez bien : StableDiffusion-XL (SDXL) et ses 2,6 milliards de paramètres. Pour l’appliquer efficacement à la restauration, les dev du projet ont du concevoir et entrainer un adaptateur de plus de 600 millions de paramètres.

Mais l’autre atout clé de SUPIR est son jeu de données d’entraînement titanesque, avec plus de 20 millions d’images haute résolution et haute qualité, chacune annotée avec une description textuelle détaillée. Cela permet à SUPIR de réaliser des restaurations guidées par des instructions en langage naturel, offrant un contrôle sans précédent sur le résultat final.

Je l’ai testé sur une image culte d’Internet : Les Horribles Cernettes. Pour ceux qui ne connaissent pas, il s’agit de la première photo qui a été envoyée via Internet à Tim Berners-Lee.

Voici l’image d’origine bien dégeu en terme de qualité :

Et voici ce que ça donne une fois passé dans SUPIR. Vous n’avez jamais vu cette photo avec cette qualité, j’en suis sûr !

Des prompts de « qualité négative » sont également utilisés pour améliorer encore la qualité perceptuelle. Et une méthode d’échantillonnage guidé par la restauration a été développée pour préserver la fidélité à l’image source, un défi courant avec les approches génératives.

Par contre, au niveau de certains détails comme les yeux, on n’y est pas encore mais je sais qu’il y a d’autres IA capable de gérer ça.

Grâce à cette combinaison unique de modèles, de données d’entraînement massives et de fonctionnalités plutôt avancées, SUPIR produit des restaurations d’une qualité exceptionnelle, en particulier sur des photos dégradées. Le tout avec la possibilité inédite de contrôler finement le résultat via des instructions en langage naturel.

Voici quelques exemples de cas d’utilisation :

  • Restaurer des paysages en faisant ressortir toute la beauté naturelle des photos
  • Obtenir des portraits ultra-détaillés et des expressions faciales quasi-parfaitement restituées
  • Redonner vie au charme des animaux dans des clichés anciens ou de faible qualité
  • Remastering de jeux vidéo pour une clarté et un niveau de détail époustouflants
  • Résurrection de films classiques pour revivre l’âge d’or du cinéma avec une netteté impeccable

Si vous ne me croyez pas, il y a plein d’exemples sur le site officiel du projet. Alors par contre, y’a pas de version en ligne officielle donc vous avez 2 possibilités pour jouer avec. Soit vous taper l’install à la main sur votre ordinateur, soit aller sur Replicate qui héberge une version en ligne avec laquelle vous pourrez améliorer vos images.

Pour en savoir plus sur SUPIR, rendez-vous sur le dépôt officiel du projet.

AI hype invades Taco Bell and Pizza Hut

A pizza hut sign in London, England.

Enlarge (credit: Getty Images)

Depending on who you ask about AI (and how you define it), the technology may or may not be useful, but one thing is for certain: AI hype is dominating corporate marketing these days—even in fast food. According to a report in The Wall Street Journal, corporate fast food giant Yum Brands is embracing an "AI-first mentality" across its restaurant chains, including Taco Bell, Pizza Hut, KFC, and Habit Burger Grill. The company's chief digital and technology officer, Joe Park, told the WSJ that AI will shape nearly every aspect of how these restaurants operate.

"Our vision of [quick-service restaurants] is that an AI-first mentality works every step of the way," Park said in an interview with the outlet. "If you think about the major journeys within a restaurant that can be AI-powered, we believe it’s endless."

As we've discussed in the past, artificial intelligence is a nebulous term. It can mean many different things depending on the context, including computer-controlled ghosts in Pac-Man, algorithms that play checkers, or large language models that give terrible advice on major city websites. But most of all in this tech climate, it means money, because even talking about AI tends to make corporate share prices go up.

Read 6 remaining paragraphs | Comments

Manger étoilé dans l’espace, c’est possible pour un demi-million de dollars

Space Perspective Neptune

Deux startups se sont associées à un chef danois renommé pour proposer un dîner exclusif à bord d'un ballon stratosphérique.

Trois pirates arrêtés dans l’affaire du piratage de France Travail

Dans une récente opération de lutte contre la cybercriminalité, trois individus ont été appréhendés suite à une investigation concernant une fuite massive de données de l'entité France Travail, selon une déclaration du parquet de Paris....

LocalAI – L’alternative open source puissante à OpenAI

Par : Korben

Aujourd’hui, j’aimerais vous présenter LocalAI, une alternative open source à OpenAI. En tout cas, c’est comme ça que le créateur du projet le présente. Il s’agit d’une solution idéale pour tous ceux qui cherchent une API REST compatible avec les spécifications de l’API OpenAI pour l’inférence locale.

Grâce à LocalAI, vous pouvez exécuter des modèles linguistiques, générer des images, de l’audio et bien d’autres choses encore, localement ou sur site avec du matériel grand public, et ce, sans avoir besoin d’un GPU ! Le projet a pour principal objectif de rendre l’IA accessible à tous.

Pour résumer, voici les principales caractéristiques de LocalAI :

  • Une API REST locale, alternative à OpenAI. Comme ça, vous gardez bien au chaud vos propres données.
  • Pas besoin de GPU. Pas besoin d’accès internet non plus. Toutefois, l’accélération GPU est possible en option.
  • Prise en charge de plusieurs modèles.
  • Dès qu’ils sont chargés une première fois, les modèles restent en mémoire pour une inférence plus rapide.
  • N’utilise pas de shell, mais des liaisons directes pour une inférence plus rapide et de meilleures performances.

En termes de fonctionnalités, LocalAI offre une large gamme d’options, parmi lesquelles :

  • La génération de texte avec les modèles GPT (comme llama.cpp ou gpt4all.cpp).
  • La conversion de texte en audio.
  • La transcription audio en texte avec whisper.cpp.
  • La génération d’images avec Stable Diffusion.
  • Les dernières fonctionnalités d’OpenAI récemment ajoutées comme l’API Vision par exemple.
  • La génération d’embeddings pour les bases de données vectorielles.
  • Les grammaires contraintes.
  • Le téléchargement de modèles directement à partir de Huggingface.

LocalAI est bien sûr un projet communautaire donc n’hésitez pas si vous souhaitez vous impliquer !

Pour commencer rapidement avec LocalAI, vous pouvez consulter leur guide Getting Started qui décrit les différentes méthodes d’installation et les exigences matérielles ou aller consulter les guides de la communauté. Je vous ferais aussi probablement un tutoriel prochainement si mon emploi du temps me le permet.

LocalAI est disponible sous forme d’image conteneur et de binaire, compatible avec divers moteurs de conteneurs tels que Docker, Podman et Kubernetes. Les images de conteneurs sont publiées sur quay.io et Docker Hub, et les binaires peuvent être téléchargés à partir de GitHub.

Concernant les exigences matérielles, ça varie en fonction de la taille du modèle et de la méthode de quantification utilisée mais pour choper quelques repères de performance avec différents backends, comme llama.cpp, vous pouvez consulter ce lien.

Maintenant pour en savoir plus, vous pouvez explorer le site localai.io. Vous y trouverez de nombreuses informations et des exemples d’utilisation pour vous aider à tirer le meilleur parti de LocalAI.

Merci à Lorenper

Ce développeur est lassé des jeux en monde ouvert : « Pas besoin de 10 000 planètes »

Thomas Mahler, directeur des jeux Ori and the Blind Forest et Ori and the Will of the Wisps, s'est exprimé sur l'accumulation des jeux en monde ouvert. Il pointe du doigt leur problème commun, avec des expériences qui cofondent souvent quantité et qualité.

US gov’t announces arrest of former Google engineer for alleged AI trade secret theft

A Google sign stands in front of the building on the sidelines of the opening of the new Google Cloud data center in Hesse, Hanau, opened in October 2023.

Enlarge / A Google sign stands in front of the building on the sidelines of the opening of the new Google Cloud data center in Hesse, Hanau, opened in October 2023. (credit: Getty Images)

On Wednesday, authorities arrested former Google software engineer Linwei Ding in Newark, California, on charges of stealing AI trade secrets from the company. The US Department of Justice alleges that Ding, a Chinese national, committed the theft while secretly working with two China-based companies.

According to the indictment, Ding, who was hired by Google in 2019 and had access to confidential information about the company's data centers, began uploading hundreds of files into a personal Google Cloud account two years ago.

The trade secrets Ding allegedly copied contained "detailed information about the architecture and functionality of GPU and TPU chips and systems, the software that allows the chips to communicate and execute tasks, and the software that orchestrates thousands of chips into a supercomputer capable of executing at the cutting edge of machine learning and AI technology," according to the indictment.

Read 6 remaining paragraphs | Comments

Après Raël, 3 séries sur des scandales médiatiques à voir sur Netflix

Les trois épisodes de Raël : Le Prophète des Extraterrestres sont désormais sur Netflix. Voici d'autres séries documentaires faisant l'anatomie de scandales particulièrement médiatisés, à voir aussi sur Netflix.

Protégez vos infos sensibles et surfez sur des sites dangereux avec Browser.lol

Par : Korben

Besoin d’accéder à un site bien chelou, bien dangereux ? Seulement, voilà, vous sanglotez de peur à l’idée de vous faire véroler.

Pas de panique, je suis là, comme d’habitude avec mes bonnes astuces.

Pour aller quand même sur une URL peu voire pas fiable du tout, il est possible de passer par un navigateur distant lancé au travers d’une sanbox. Et c’est exactement ce que propose le site Browser.lol.

Avec des fonctionnalités comme l’accès illimité, vous pouvez contourner les restrictions géographiques pour accéder à des contenus bloqués dans certaines localités. Cela garantit la protection de votre vie privée en ligne, permettant une navigation anonyme et sécurisée de votre identité numérique.

C’est également pratique pour vérifier la compatibilité des sites web avec différents navigateurs et appareils. De plus, l’outil permet de débloquer des sites web qui sont restreints sur un réseau ou par une organisation. Comme ça tout paaasssseeee !

Sur Browser.lol, vous trouverez plusieurs navigateurs comme Chrome, Firefox, Edge, ou encore Bravo, Opera et Tor, afin de faire vos tests.

Le site offre également des capacités de test de vulnérabilité pour identifier les failles de sécurité sur les sites web. Et pour les recherches discrètes (hmm-hmm), l’outil assure une recherche incognito, vous permettant de naviguer sans laisser de trace.

Enfin, l’expérience de navigation est améliorée par un blocage efficace des publicités, et le masquage du trafic permet de garder vos activités internet privées, loin des yeux de votre réseau local et de votre fournisseur d’accès internet.

Bref, c’est le genre de site bien pratique à garder dans vos favoris.

SFTPGo – Le serveur SFTP ultime pour vos transferts de fichiers

Par : Korben

Imaginez que vous deviez partager des fichiers avec vos collaborateurs, travailler sur des projets avec des personnes situées aux quatre coins du monde ou simplement sauvegarder vos photos de vacances, mais que vous ne savez pas par quoi commencer ?

Et bien, ne cherchez plus, SFTPGo est là pour vous faciliter la vie.

SFTPGo c’est un serveur SFTP open source, complet et hautement configurable qui supporte HTTP/S, FTP/S ou encore WebDAV. Il prend en charge plusieurs backends de stockage : du système de fichiers local avec ou sans chiffrement, du stockage d’objets S3, du Google Cloud Storage, de l’Azure Blob Storage, et bien sûr, SFTP.

L’outil est gratuit, mais si vous voulez le soutenir ou profiter d’un support technique, il faudra porter la main à la bourse ^^. C’est donc plus Open Bourse qu’Open Source.

Parmi les fonctionnalités offertes, on trouve la possibilité de créer des dossiers virtuels privés ou partagés, des commandes personnalisables, des comptes virtuels stockés, de l’isolement chroot, des autorisations virtuelles par utilisateur et par répertoire, ainsi qu’une API REST, un gestionnaire d’événements, une interface d’administration…etc.

SFTPGo facilite le paramétrage d’une authentification multifacteur personnalisable. Authentification partielle, par utilisateur et avec plusieurs méthodes, incluant l’authentification LDAP/Active Directory et des programmes externes. Il supporte l’administration des utilisateurs, le chiffrement des données, la modification dynamique des utilisateurs, les quotas, la limitation de bande passante et de débit.

Pour sécuriser vos données, SFTPGo propose une limitation du nombre de sessions simultanées avec ou sans filtrage par IP ou dossier. Terminaison automatique des connexions inactives, gestion de liste de blocage, filtrage Geo-IP et il est bien sûr compatible avec Git, SCP, rsync, FTP/S et WebDAV.

Pour vous faciliter la vie, SFTPGo propre aussi des analyses de performance, des logs ultra-précis et un support Infrastructure as Code (IaC) via Terraform. Il est compatible avec Linux, macOS, Windows et FreeBSD et nécessite Go ainsi qu’un serveur SQL. Des binaires et une image Docker officielle sont également disponibles.

SFTPGo est disponible sur plusieurs plateformes, y compris les dépôt Ubuntu, Void Linux, AWS Marketplace, Azure Marketplace et Elest.io. Il est également disponible pour Windows et macOS via des packages tels que winget, Chocolatey et Homebrew. Et il existe des portages pour FreeBSD et DragonFlyBSD.

Voilà, si vous cherchez un serveur SFTP totalement configurable (y’a même un système de plugins) et supportant S3, Google Cloud, Azure et j’en passe, celui-ci est un must-have !

DietPi – Une Debian ultra légère pour Raspberry Pi, Odroid, PINE64…etc optimisée et personnalisable

Par : Korben

Si vous aimez les ordinateurs un peu légers, type Raspberry Pi, Odroid et j’en passe, alors DietPi est fait pour vous. Il s’agit d’un système d’exploitation basé sur une Debian allégée dans le but de consommer le moins de CPU et de RAM possible.

Voici un tableau qui compare DietPi avec Raspberry Pi OS Lite (64 bits). On peut y voir que niveau RAM, on économise 58%, sur le CPU c’est 39% en moyenne et en matière d’espace disque, c’est plus léger de 41%. Évidemment, cela se ressent sur la rapidité du boot, puisque c’est plus rapide à démarrer de 73%.

Avec DietPi, vous bénéficiez de paramètres personnalisables pour configurer votre système selon vos besoins, et vous pouvez facilement gérer les priorités de vos logiciels. De plus, le système prend en charge les mises à jour automatiques et l’automatisation de l’installation grâce à un dietpi.txt dans lequel vous pouvez spécifier votre config (genre les accès wifi, l’activation du serveur ssh…etc).

DietPi est également livré avec un utilitaire de Backup ce qui vous permettra très facilement de sauvegarder et de restaurer votre installation.

Comme je le disais, DietPi est compatible avec une variété d’ordinateurs, notamment les modèles Raspberry Pi, Odroid, PINE A64 et bien d’autres.

Les machines virtuelles telles que Hyper-V, Virtualbox, Vmware, Parallels, UTM et Proxmox sont également prises en charge par DietPi, ce qui vous permet de l’utiliser lorsque les performances des micro-ordis sont insuffisantes. Ça peut même tourner sur un bon vieux PC x86/64.

Pour en savoir plus sur DietPi et comment l’utiliser, je vous invite à consulter le site officiel ici. Vous y trouverez des informations détaillées sur les différentes fonctionnalités offertes par DietPi, ainsi que des conseils pour bien démarrer avec ce système d’exploitation léger et optimisé.

En résumé, DietPi est un choix fantastique pour ceux qui souhaitent tirer le meilleur parti de leur matériel, tout en minimisant la consommation de ressources. Qu’il s’agisse de créer un serveur NAS, d’expérimenter avec des projets IoT ou simplement de vous familiariser avec le monde des SBC (Single Board Computer), DietPi vous permettra de vous lancer rapidement et en toute simplicité.

Comment Pinterest a monté son PaaS Kubernetes

Pinterest a entrepris de moderniser son infrastructure de calcul avec Kubernetes. Des API à la sémantique, il y a greffé ses outils et processus.

e-Presto Max : ce très bon scooter équivalent 125 est moins cher

[Deal du jour] L'e-Presto Max, de la marque française Easy-Watts, est un excellent scooter électrique équivalent 125 cm³. Son joli design et ses bonnes performances en font un deux-roues pratique en ville. Il devient plus abordable avec cette promotion.

Man dies on way home from Panera after having three “charged” lemonades

Par : Beth Mole
Dispensers for Charged Lemondade, a caffeinated lemonade drink, at Panera Bread, Walnut Creek, California, March 27, 2023.

Enlarge / Dispensers for Charged Lemondade, a caffeinated lemonade drink, at Panera Bread, Walnut Creek, California, March 27, 2023. (credit: Getty | Smith Collection/Gado)

A second person has died after drinking Panera's caffeinated "Charged Lemonade" drinks, which contain caffeine levels comparable to strong coffee and are sold in cups as large as 30 fluid ounces that are free to refill.

According to a lawsuit filed by family members Monday, 46-year-old Dennis Brown fell dead on a sidewalk from cardiac arrest while walking home from a Panera in Florida on October 9. Before he left the restaurant, he had ordered a Charged Lemonade and had two refills.

In September, college student Sarah Katz, 21, went into cardiac arrest after drinking a Charged Lemonade from a Panera in Philadelphia. Katz had a heart condition called long QT syndrome type 1 and had avoided energy drinks because of it, according to a lawsuit filed in October by her family.

Read 9 remaining paragraphs | Comments

7shifts Payroll Review 2023: Features, Pricing, Pros & Cons

Par : Ian Agar
This restaurant management and payroll platform is highly affordable and user-friendly. But it’s not built for large, multi-location operations.

Restaurant365 Workforce Review 2023: Features, Pros & Cons

Par : Ian Agar
This restaurant management platform is broad and solves most day-to-day business needs. You’ll pay a hefty price in time and money, though.

Unproven AI face scans may estimate age for porn access in UK

Unproven AI face scans may estimate age for porn access in UK

Enlarge (credit: Aurich Lawson | Getty Images)

AI face detection now counts among the tools that could be used to help adult sites effectively estimate UK user ages and block minors from accessing pornography, the UK's Office of Communications (Ofcom) said in a press release on Tuesday.

The only foreseeable problem, Ofcom noted: There's little evidence that the AI method of age estimation will be fair, reliable, or effective.

The UK's legal age to watch porn is 18. To enforce that restriction, under the Online Safety Act, Ofcom will soon require all apps and sites displaying adult content to introduce so-called "age assurance" systems that verify and/or estimate user ages. Sites and apps risk potential fines if they fail to "ensure that children are not normally able to encounter pornography on their service."

Read 11 remaining paragraphs | Comments

Massive power makes this electric restomod Mini Cooper a handful

The front half of a classic Mini Cooper, seen by the sea.

Enlarge / The classic Mini Cooper made barely 60 hp by the time it bowed out in the mid-'90s. Gildred Racing will make you one with far more power, with either a mid-mounted V6 or, like this blue car, a Tesla drive unit. (credit: Gildred Racing)

Monterey Car Week always brings out the automotive industry’s heavy hitters, from world-class vintage cars to brand-new seven-figure track toys, classic Vespa scooters, and everything in between. And yet, a surprising duo wound up as my favorite experience of the week: driving a pair of two tiny “Super Coopers” brought to Monterey by Gildred Racing to promote the debut of a new Tesla-powered electric project.

The company's Super Cooper electric powertrain conversion might have deserved the lion’s share of headlines as the latest and greatest offering, but the company’s previous Super Cooper “S” also delivers an absurd 502 hp (375 kW) to the rear wheels from a mid-mounted supercharged V6.

Taking an expansive view, the pair truly serves as a microcosm that perfectly encapsulates the current enthusiast industry, right down to the differences between rear- and front-wheel drive—and even to this day, I can’t decide which I liked more.

Read 20 remaining paragraphs | Comments

Australia Needs to Prepare to Reap the Benefits of Artificial Intelligence

Par : Ben Abbott
Australia’s international standing in artificial intelligence research is one indicator of strong local expertise and potential in AI, according to the CSIRO, but community buy-in could hold the country back.

Old-school problems, old-school solutions: We help aero-test a Mustang

A white Ford Mustang GT350 restomod with blue stripes, with the mountains of Willow Springs in the background

Enlarge / OVC's Shelby Mustang recreations are accurate enough to be granted official papers to compete in historic racing. (credit: Michael Teo Van Runkle)

To Shelby Mustang fans, the Original Venice Crew (OVC) is the stuff of legends. This was the actual team that designed and built the original GT350s, Cobras, Daytona Coupes, and GT40s that introduced Carroll Shelby's name to the masses. Today, OVC builds modern Mustang re-creations so accurately that one was approved for last year's Le Mans Classic, which celebrated 100 years of the world's most famous endurance race.

But OVC also offers updated versions of those classics, bringing to life ideas that bounced around the shop back in the day but that Shelby never built in series production. Want a 1965 GT350 with independent rear suspension? OVC can do that, after dialing in a design that Ford originally believed would be too expensive as a replacement for the first-gen Mustang's solid rear axle.

These projects don't quite fit under the "restomod" umbrella, instead falling more along the lines of the ideas that OVC founder and boss Jim Marietta remembers from his days back at 1042 Princeton Drive. Think fender flares cut by hand rather than being machined or updated fiberglass front fascias to provide additional airflow.

Read 14 remaining paragraphs | Comments

Former Ubisoft executives reportedly arrested over sexual assault allegations

Former Ubisoft executives reportedly arrested over sexual assault allegations

Enlarge (credit: Getty Images / Ubisoft / Aurich Lawson)

Five former Ubisoft executives have reportedly been detained for questioning by French authorities, years after they departed from the company amid widespread sexual assault allegations.

According to a report from France's Libération newspaper (as translated by GamesIndustry.biz), this week's arrests by the Bobigny public prosecutor's office include Ubisoft's former chief creative officer Serge Hascoët and ex-VP of editorial and creative services, Tommy François. Hascoët resigned from the company in July 2020, while Francois left less than a month later. A year after those departures, French labor union Solidaires Informatique worked with two of the alleged victims to file a formal complaint about the alleged assaults, which seems to have led to this week's move by French police.

It's not immediately clear who else has been caught up in this week's police actions or whether the former executives will be released from detention after questioning. Other high-profile Ubisoft employees who resigned or were fired amid the 2020 allegations include Assassin's Creed Valhalla director Ashraf Ismail, former Ubisoft Canada managing director Yannis Mallat; former Ubisoft PR director Stone Chin; former Ubisoft global head of HR Cécile Cornet, and former Ubisoft vice president of editorial Maxime Beland.

Read 4 remaining paragraphs | Comments

This EV restomod highlights the joys and flaws of the classic MGB

A metallic green MGB drives down an English road

Enlarge / Mass-produced in the 1960s with a not-very special engine, the MGB is a rather good candidate for an electric conversion. (credit: Frontline Developments)

Electrifying classic sports cars is swiftly becoming big business. Battery-powered 911s, E-Types, Triumphs, and more have been around for a while, but the humble MGB has thus far been overlooked… until now. UK-based MG specialists Frontline Developments has a rich history of restoring, modifying, and generally sprucing up MGBs, and has decided that now is the time to inject a cleaner, greener heart into what was once a British sportscar staple.

The MG BEE EV is a neat little thing. Currently in prototype form, it's packing a 40 kWh battery attached to a 114 hp (85 kW) 162 lb ft (220 Nm) Hyper9 motor that sends power to the rear wheels via a five-speed Mazda Miata gearbox. Range is about 140 miles (225 km) if you drive sensibly, and charging takes about five hours. Frontline will build you one as a BEE GT (coupe), or Roadster should you wish to feel the wind in your beard as you roll along.

Frontline Developments is well known in the MG world. Founded in 1991 by Tim Fenna, it started with gearbox swaps, then widened its business with suspension, brake, and even engine upgrades for customers wanting a little more go. The company offers full restorations, as well as its own special editions from time to time. Its LE50 and Abingdon editions came with beautiful aesthetics, twinned with more modern (and powerful) internal combustion engines. It's launching a V8-powered LE60 alongside the BEE for those who fancy old-school thrills.

Read 10 remaining paragraphs | Comments

The Trillion-Dollar Grift: À l’intérieur de la plus grande arnaque de tous les temps

Le vol des allocations chômage aux États-Unis est qualifié de plus grande arnaque de tous les temps. Des milliards de dollars se sont envolés dans les poches d'escrocs....

Windows Update Restored : L’initiative audacieuse pour la mise à jour des vieux Windows !

Une équipe d'amateurs d'ordinateurs rétro a lancé le projet indépendant "Windows Update Restored" avec une mission audacieuse : faciliter la mise à jour des anciennes versions de Windows....

Comment Pinterest a implémenté la détection d’anomalies

Pinterest évoque la mise en œuvre de sa plate-forme de détection d'anomalies face au spam et à la dérive des modèles de machine learning.

Moscou a du mal à gérer ses propres policiers pirates

Des mesures viennent d'être prises en Russie aprés la découverte de policiers commercialisant des données personnelles tirées des bases de données de leur service !...

Devenez le roi du multi-stream avec Restreamer !

Par : Korben

Vous aimez faire le mariole sur Youtube en live et c’est trop cool de pouvoir parler à des tas de gens en même temps et de montrer vos exploits sur Minecraft. Mais vous avez également une communauté sur TikTok, Twitch et Instagram…etc.

Alors comment faire pour contenter tout ce petit monde ? Changer de plateforme tout au long de la journée ?

Trop le bordel, alors vous laissez tomber.

Aaaah si seulement vous aviez eu un outil pour faire du multi-stream ! Eh bien, ne cherchez pas plus loin : Restreamer est là pour vous sauver !

Restreamer est un serveur vidéo open-source facile à utiliser, qui offre une interface sympa et ainsi qu’une API. Ainsi, il est capable de diffuser votre flux en direct sur n’importe quelle plateforme vidéo de l’univers (Twitch, Youtube, TikTok, Instagram…etc) en même temps et sans payer de coût de licence.

Restreamer, la solution ultime pour le multi-streaming

Parmi les fonctionnalités de Restreamer, on retrouve la possibilité de configurer des flux vidéo en direct, de surveiller les statistiques, de contrôler la bande passante et surtout de gérer plusieurs sources vidéo. Et pour ceux qui se demandent, oui si vous êtes Partenaire Twitch, vous pouvez faire un live simultané sur une plateforme mobile comme TikTok ou Instagram… mais pas Youtube Live.

Sachez que Restreamer est compatible avec divers protocoles de streaming tels que RTMP, RTSP, HLS, DASH et SRT et qu’il fonctionnera aussi bien sous Linux, que macOS ou Windows, ainsi que sur Raspberry Pi et autres petits ordinateurs du style.

Pour installer Restreamer, assurez-vous d’avoir Docker installé sur votre système puis lancez la commande suivante dans votre terminal pour télécharger et exécuter l’image Docker de Restreamer :

docker run -d --restart=always --name restreamer \ -p 8080:8080 -p 8181:8181 -p 1935:1935--privileged \ datarhei/restreamer:latest
Logiciel de multi-streaming pour diffuser simultanément sur plusieurs plateformes

Il est libre, sous licence Apache 2.0, ce qui signifie qu’il est gratuit pour un usage privé et commercial et vous pouvez télécharger sa dernière version directement depuis le site officiel.

Une démo est là pour ceux qui veulent en voir plus. (user : admin / pass : demo)

Merci à JohnnyBeGood pour le partage !

Darkweb : 288 arrestations dans une vaste opération anti pirates

Interpol vient de frapper un nouveau coup sur la tête numérique du dark web. 288 arrestations de hackers malveillants, et plus de 50 millions d'euros saisis....

Un pirate ukrainien arrêté pour avoir vendu des données à la Russie

Un hacker malveillant ukrainien a été arrêté par les autorités après avoir vendu 300 millions de données piratées à des pirates étrangers, dont des Russes....

Organisez vos comics, magazines et livres avec Komga

Par : Korben

Si vous cherchez un bon moyen d’auto-héberger vos magazines, vos livres et bandes dessinées, ne cherchez plus, Komga est la solution !

Si les comics vous intéressent et que vous avez tout ça au format numérique, c’est forcement un peu galère pour organiser tout ça et s’y retrouver. Grâce à Komga vous pourrez vous sortir de ce pétrin et créer des bibliothèques pour vos BDs afin d’organiser totalement vos collections.

Komga est donc un serveur de comics / mangas open source et gratuit. Vous pouvez même y mettre vos magazine PDF ou vos livres. Il supporte les formats epub, pdf, cbz et cbr et une fois en place, vous profiterez d’une jolie d’une interface web responsive.

Organisez vos comics avec Komga

Vous pourrez ainsi organiser votre bibliothèque avec des collections et des listes de lecture, et même modifier les métadonnées de vos séries de BDs et de vos livres. Komga permet également d’importer automatiquement les métadonnées intégrées à ces fichiers et vous pouvez tout lire sans quitter votre navigateur via le lecteur web.

Gérez vos magazines avec Komga

D’ailleurs plusieurs modes de lecture sont dispo et vous pouvez même gérer plusieurs users avec un contrôle d’accès par bibliothèque, mais également des restrictions d’âge.

En plus de cela, il dispose d’une API REST et de nombreux outils et scripts développés par la communauté qui sont capables d’interagir avec Komga.

Vous pourrez, d’un clic, télécharger les fichiers à l’unité ou des séries entières de BDs entières et si vous avez des petits soucis de mémoire lors de vos imports, l’outil est également capable de détecter les fichiers en double et même les pages en double. Komga peut également importer automatiquement les BDs déposées dans un répertoire.

Stockez vos livres avec Komga

Le plus beau là-dedans, c’est que ça s’installe très facilement avec Docker Compose, ou lancé directement via le .jar fourni (java). Donc vous l’aurez compris, ça peut tourner sur un Windows, un Linux mais également un NAS.

Si vous voulez tester par vous-même, une démo est accessible ici : https://demo.komga.org/

  • Login: demo@komga.org
  • Password: komga-demo

La police arrête 7 pirates de données

Sept hackers malveillants ont été arrêtés suite à la diffusion d'une base de données de plus de 16 millions de citoyens. Cette base pirate a été vendue plus d'une centaine de fois !...

Jarg – Une interface graphique pour Restic

Par : Korben

Vous vous souvenez de Restic que je vous ai présenté en 2020 ?

Ce logiciel permet de faire des backup sous forme de snapshot (object storage) localement ou sur des services distants type AWS S3, OpenStack Swift, BackBlaze B2, Microsoft Azure Blob Storage ou encore Google Cloud Storage sans oublier via SFTP.

Sauf que Restic, et bien c’est de la ligne de commande et je sais que certains d’entre vous sont allergiques à ça. Heureusement, il existe une interface graphique (moche) nommée Jarg qui devrait vous aider à prendre ça en main.

Il vous faudra évidemment télécharger et installer Restic avant de pouvoir utiliser cette application.

Capture d'écran de l'interface graphique Jarg pour Restic

Lors de votre première utilisation de Jarg, un profil « par défaut » sera alors créé, ainsi qu’un « répertoire restic » dans votre dossier utilisateur et c’est votre dossier courant qui sera utilisé comme source pour la sauvegarde.

Jarg exécutera alors les commandes Restic correspondantes à ce que vous voulez et affichera les résultats affichés sur la droite de l’interface.

Notez que niveau sécurité, Jarg ne chiffre pas pour le moment les mots de passe et les secrets S3 donc soyez prudent avec la sécurité de votre ordinateur.

Jarg est dispo sous macOS, Windows et Linux (soit vous compilez, soit vous utilisez l’AppImage) en cliquant ici.

Restaurez vos vieilles photos avec l’IA grâce à DifFace

Par : Korben

On a tous de vieilles photos qui trainent dans nos archives et notamment de vieux JPEG qui datent d’une époque où la compression d’image était vraiment dégradée. Mais grâce à l’algo DifFace qui utilise de l’IA, il est possible de gérer les dégradations complexes d’une photo pour la restaurer.

Et je dois dire que le résultat est bluffant. Alors tout le code se trouve sur Github et vous pouvez le déployer de votre côté, mais si la flemme est ce qui conditionne l’ensemble de votre vie, le plus simple est encore d’aller sur HuggingFace (édit : ça marche plus, passez par le Colab plutôt).

Comparaison entre une photo originale et sa version restaurée avec DifFace

Vous uploadez votre image, vous cliquez sur « Soumettre » et voilà ! vous aurez un super résultat qui fera plaisir à votre petit coeur.

Schéma illustrant le fonctionnement de DifFace pour la restauration de photos

J’ai testé beaucoup d’outils similaires, mais je crois que celui-ci fournit la meilleure des restaurations, y compris quand c’est hyper hyper flou… Même si évidemment, tout n’est pas encore parfait puisqu’en zoomant, on a encore ce petit côté « dessiné sur l’image », mais on y arrive doucement.

Portrait en noir et blanc restauré avec DifFace

Je vous invite vraiment à le tester et à le comparer avec d’autres systèmes similaires.

Le FBI saisi le site des pirates du groupe HIVE

Le site darkweb des hackers malveillants du groupe HIVE, des pirates informatiques spécialisés dans le rançonnage d'entreprises, saisi par les autorités américaines....

La police débarque dans une startup du phishing : 41 arrestations

Les autorités ont mis fin au business d'une entreprise pas comme les autres spécialisées dans le détournement de comptes bancaires. Des dizaines de personnes arrêtées...

Arnaque au compte personnel de formation : 14 personnes arrêtées

La Gendarmerie Nationale française arrête quatorze personnes soupçonnées de piratage et détournement de fonds. Ils se cachaient derrière des arnaques au compte personnel de formation (CPF)....

Un membre de Lockbit arrêté au Canada

Europol a annoncé aujourd'hui l'arrestation d'un ressortissant russe lié aux attaques du rançongiciel LockBit ciblant des organisations d'infrastructures critiques et des entreprises de premier plan dans le monde entier....

Comment coder une API RESTful ?

Par : Korben

— Article en partenariat avec talent.io —

Certains pensent que le monde se divise en deux avec d’un côté le bien et de l’autre le mal. Mais la vérité est ailleurs surtout pour les développeurs qui savent que le monde se divise en réalité entre le Frontend et le Backend.

Et pour que ces 2 faces d’une même pièce puissent « discuter », il nous faut des API. API, ça veut dire Application Programming Interface et c’est tout simplement un ensemble d’instructions permettant aux applications de communiquer entre elles. Maintenant des types d’API, il y en a des tonnes, mais je vous propose qu’aujourd’hui on s’intéresse aux API qui respectent le standard architectural REST.

En effet, quand on travaille en tant que développeur, on ne peut pas passer à côté des API REST, tant cette pratique est très répandue. Si vous débutez dans votre métier, c’est forcement quelque chose que vous devez apprendre et maitriser. De la même manière, quand on débute sa carrière de développeur ou qu’on a déjà beaucoup d’années au compteur mais qu’on ne connaît pas sa valeur sur le marché de l’emploi, il est bon de connaître la grille des salaires en France. Ça tombe bien puisque talent.io a mis en ligne une étude des salaires de la tech en 2022 pour que vous puissiez déterminer si votre salaire est correct ou sous évalué.

Je vous invite à vous plonger dedans afin de savoir où vous vous situez sur cette grille des salaires.

C’est quoi une API RESTful ?

REST, ça veut dire « Representational State Transfer ». Lorsqu’une API respecte les contraintes de REST, on parle alors d’une API RESTful.

Quand un développeur veut créer une API RESTful, il doit alors respecter les contraintes édictées par REST, notamment sur le fait que son API doit fonctionner au travers du protocole HTTP et de ses verbes (GET, POST…etc.) et que les requêtes et les réponses de l’API soient dans un format texte tels que JSON, HTML, XML…etc.

Les API RESTful sont alors mises à disposition des applications via ce qu’on appelle des endpoints. Un endpoint est un assemblage de 2 choses : une URI et un verbe HTTP.

Admettons que j’ai une API qui permette de lister des utilisateurs, mais également d’en créer des nouveaux.

L’URI de mon API est la suivante :

https://url.com/api/user

Le but du jeu, c’est d’appeler par exemple ce endpoint avec le verbe GET pour obtenir une liste de tous les utilisateurs.

GET: /user/

Ou pour ajouter un nouvel utilisateur, on peut utiliser le verbe POST comme ceci, en transmettant un bout de JSON contenant toutes les informations liées à l’utilisateur qu’on souhaite créer (nom, prénom…etc.) :

POST: /user/

L’idée là, c’est de vous montrer qu’on peut interagir avec l’API à l’aide de différents verbes HTTP. Get peut être assimilé au verbe « lire », POST au verbe « créer », PUT et PATCH au verbe « Mettre à jour » et DELETE au verbe « supprimer ». C’est aussi simple que cela. Et en retour le serveur peut alors répondre avec des codes de status HTTP classiques comme 200, 201, 2002…etc. pour dire que tout est OK, ou des codes de redirection 3xx, d’erreur client 4xx ou d’erreur serveur 5xx.

En ce qui concerne le format utilisé par les requêtes et les réponses, vous pouvez utiliser du texte, peu importe son format (html, xml.etc.), mais par convention, on utilise surtout du JSON (JavaScript Object Notation).

Et JSON ?

Le JSON a la particularité d’être facile à lire et à écrire pour les humains et est utilisé pour enregistrer des données dans des bases de données, mais également pour transmettre ces données entre les applications. C’est pourquoi on l’utilise dans les API RESTful.

Le JSON est une collection de paires nom / valeur qui sont ordonnées dans une liste. Ainsi les valeurs contenues dans le JSON peuvent être une chaine de caractère (string), un nombre, mais également des objets JSON, des tableaux de valeurs (Array), des booléens (true / false) ou la fameuse valeur null.

Les contrôles hypermedia

Je ne vais pas les aborder en détail pour ne pas alourdir cette initiation débutant mais sachez que pour qu’une API soit RESTful, elle doit en plus de tous ces aspects, intégrer également la notion de contrôle hypermedia (Hypermedia as the Engine of Application State – HATEOAS). C’est un attribut de REST qui permet de renvoyer des liens hypertextes afin d’indiquer les actions disponibles directement dans les réponses JSON

Voilà concernant les grands principes des API RESTful.

Comment créer votre première API RESTful ?

Maintenant je vous propose qu’on apprenne à en créer une de zéro. Vous allez voir, c’est super simple.

Pour cette démo, j’ai choisi d’utiliser Python comme d’habitude. Et je vais importer dans mon code le framework Flask qui va me permettre de faire monter mon API RESTful très facilement. Installez Flask comme ceci :

pip3 install flask-restful

Pour tester l’API, nous allons utiliser un outil qui permet à la fois de balancer nos requêtes et de voir si les réponses correspondent bien. L’un des plus connus s’appelle Postman et c’est gratuit en version de base pour tester. L’application Desktop de Postman est disponible ici.

Ensuite, nous allons définir ce que va faire notre API. Ce sera quelque chose d’assez simple permettant de créer, supprimer, lire et mettre à jour des données. Admettons que j’ai un site sur lequel je dois référencer des produits. Chacun de ces produits aura un id, un nom, un prix et une catégorie.

Le code de votre première API

Je vais donc créer un fichier productAPI.py et je vais importer Flask comme ceci avec ses imports spécifiques aux API et au parsing JSON :

from flask import Flask
from flask_restful import Resource, Api, reqparse

app = Flask(__name__)
api = Api(app)

Puis je vais créer une espèce de mini base de données JSON directement dans mon code afin d’y référencer mes produits :

products = [
    { "id": 1, "name": "Stylo 4 couleurs", "price": 10, "category": "Papeterie" },
    { "id": 2, "name": "Cahier vert", "price": 20, "category": "Papeterie" },
    { "id": 3, "name": "Télévision 4K", "price": 30, "category": "Tech" },
    { "id": 4, "name": "Souris sans fil", "price": 40, "category": "Tech" },
    { "id": 5, "name": "Ananas", "price": 50, "category": "Alimentaire" },
    { "id": 6, "name": "Kinder Bueno", "price": 60, "category": "Alimentaire" },
    { "id": 7, "name": "Chemise de président", "price": 70, "category": "Textile" },
    { "id": 8, "name": "T-shirt de punk", "price": 80, "category": "Textile" },
    { "id": 9, "name": "Tournevis bleu", "price": 90, "category": "Bricolage" },
    { "id": 10, "name": "Marteau rouge", "price": 100, "category": "Bricolage" }
    ]

Maintenant on va créer une classe Product qui sera vu comme un endpoint au niveau de notre API. Et dans cette class, nous allons placer nos 4 fonctions correspondantes aux 4 verbes HTTP dont je vous ai parlé plus haut.

class Product(Resource):

    def get(self, id):

    def post(self, id):

    def put(self, id):

    def delete(self, id):

La structure de base de notre API est OK. Maintenant, on va définir chacune de ces fonctions en commençant par la fonction get utilisée pour récupérer les informations d’un produit à partir de son ID. Comme vous pouvez le voir, on fait une boucle « for » qui va parcourir l’ensemble des produits et si l’ID correspond à ce qui spécifié dans la requête, on renvoie l’objet « product » avec son code HTTP 200 et si ce n’est pas le cas, on renvoie un message « Produit introuvable » accompagné d’un code d’erreur HTTP 404 qui correspond à une ressource non trouvée.

    def get(self, id):
        for product in products:
            if (id == product["id"]):
                return product, 200
        return "Produit introuvable", 404

La fonction suivante va nous permettre de créer un nouveau produit. La donnée utilisée dans la requête étant structurée en JSON, cette fonction va utiliser le parseur de Flask pour extraire toutes les données du JSON et les ajouter à notre tableau de produits :

    def post(self, id):
        parser = reqparse.RequestParser()
        parser.add_argument("name")
        parser.add_argument("price")
        parser.add_argument("category")
        args = parser.parse_args()

        for product in products:
            if (id == product["id"]):
                return "Ce produit {} existe deja".format(id), 400

        product = {
            "id": id,
            "name": args["name"],
            "price": args["price"],
            "category": args["category"]
        }
        products.append(product)
        return product, 201

Une fois que le produit est créé, on retourne le code 201 qui veut dire que la création s’est bien déroulée. Et si le produit existait déjà avec cet ID, on renvoie le code 400 avec un message d’erreur.

La fonction put suivante est assez similaire puisqu’elle permet à la fois de créer un nouveau produit (si l’id n’est pas encore utilisé) ou de mettre à jour un produit existant.

    def put(self, id):
        parser = reqparse.RequestParser()
        parser.add_argument("name")
        parser.add_argument("price")
        parser.add_argument("category")
        args = parser.parse_args()

        for product in products:
            if (id == product["id"]):
                product["name"] = args["name"]
                product["price"] = args["price"]
                product["category"] = args["category"]
                return product, 200

        product = {
            "id": id,
            "name": args["name"],
            "price": args["price"],
            "category": args["category"]
        }
        products.append(product)
        return product, 201

Enfin, vous l’aurez compris, la fonction delete permettra de supprimer un enregistrement à partir de son ID.

    def delete(self, id):
        global products
        products = [product for product in products if product["id"] != id]
        return "{} is deleted.".format(id), 200

Une fois ces fonctions définies, il ne reste plus qu’à spécifier le format de l’URI qui sera utilisé pour appeler l’API et lancer l’API (en mode debug pour démarrer). Le paramètre <int:id> permet d’indiquer que dans le chemin du endpoint, on peut ajouter une variable acceptée par l’API (ici l’ID du produit).

api.add_resource(Product, "/product/<int:id>")
app.run(debug=True)

Tester l’API avec Postman

Enfin, il ne reste plus qu’à lancer le script python à l’aide de la commande suivante :

python3 productAPI.py

Le serveur web de Flask se lancera alors et vous verrez apparaitre une URL locale que vous pourrez appeler dans Postman pour ensuite tester votre API.

Voici le code complet du script pour information.

from flask import Flask
from flask_restful import Resource, Api, reqparse

app = Flask(__name__)
api = Api(app)

products = [
    { "id": 1, "name": "Stylo 4 couleurs", "price": 10, "category": "Papeterie" },
    { "id": 2, "name": "Cahier vert", "price": 20, "category": "Papeterie" },
    { "id": 3, "name": "Télévision 4K", "price": 30, "category": "Tech" },
    { "id": 4, "name": "Souris sans fil", "price": 40, "category": "Tech" },
    { "id": 5, "name": "Ananas", "price": 50, "category": "Alimentaire" },
    { "id": 6, "name": "Kinder Bueno", "price": 60, "category": "Alimentaire" },
    { "id": 7, "name": "Chemise de président", "price": 70, "category": "Textile" },
    { "id": 8, "name": "T-shirt de punk", "price": 80, "category": "Textile" },
    { "id": 9, "name": "Tournevis bleu", "price": 90, "category": "Bricolage" },
    { "id": 10, "name": "Marteau rouge", "price": 100, "category": "Bricolage" }
    ]

class Product(Resource):
    def get(self, id):
        for product in products:
            if (id == product["id"]):
                return product, 200
        return "Product not found", 404

    def post(self, id):
        parser = reqparse.RequestParser()
        parser.add_argument("name")
        parser.add_argument("price")
        parser.add_argument("category")
        args = parser.parse_args()

        for product in products:
            if (id == product["id"]):
                return "Ce produit {} existe deja".format(id), 400

        product = {
            "id": id,
            "name": args["name"],
            "price": args["price"],
            "category": args["category"]
        }
        products.append(product)
        return product, 201

    def put(self, id):
        parser = reqparse.RequestParser()
        parser.add_argument("name")
        parser.add_argument("price")
        parser.add_argument("category")
        args = parser.parse_args()

        for product in products:
            if (id == product["id"]):
                product["name"] = args["name"]
                product["price"] = args["price"]
                product["category"] = args["category"]
                return product, 200

        product = {
            "id": id,
            "name": args["name"],
            "price": args["price"],
            "category": args["category"]
        }
        products.append(product)
        return product, 201

    def delete(self, id):
        global products
        products = [product for product in products if product["id"] != id]
        return "{} is deleted.".format(id), 200

api.add_resource(Product, "/product/<int:id>")
app.run(debug=True)

Côté Postman, un simple GET se forme ainsi et renvoie l’intégralité du JSON propre au produit (grâce à son ID) :

Pour faire un POST, il faut bien penser à indiquer qu’on souhaite transmettre un contenu de type « RAW » au format JSON et appeler le endpoint avec l’ID de notre nouveau produit (ce n’est pas l’idéal bien sûr, car le principe d’un nouvel ID c’est qu’il soit généré directement par le code de l’API, mais c’est pour illustrer mon exemple).

Ensuite pour la mise à jour avec le verbe PUT, ça donne ça…

Et pour la suppression, on obtient ce genre de retour :

Et ensuite ?

Vous l’aurez compris, ce n’est vraiment pas compliqué à développer. Ici on est sur un exemple simple, mais ensuite, vous devrez pourquoi pas sortir vos données d’une base de données, penser à correctement gérer les erreurs et faire preuve de rigueur dans la structure de vos endpoints. Par exemple, dans mon endpoint, l’URI est xxxx/product/. J’aurais pu faire mieux en respectant la convention et en mettant/products/ au pluriel. Car en cas de GET, je peux aussi demander à récupérer l’ensemble des produits existants. Dans ce cas, je dois modifier ma fonction GET comme ceci :

    def get(self, id):
        if (id == 0):
            return products, 200
        else:
            for product in products:
                if (id == product["id"]):
                    return product, 200
            return "Product not found", 404

Ainsi, en passant l’id 0 lors de mon GET, je récupérerai alors tous les produits.

N’oubliez pas également de documenter l’ensemble de votre API afin de vous y retrouver et surtout d’indiquer à d’autres développeurs, comment l’intégrer. Penchez vous également sur l’aspect HATEOAS pour intégrer les actions disponibles dans les réponses de l’API REST. Pour notre exemple, on pourrait ainsi avoir quelque chose qui ressemble à ça :

"links": [ 
    {"rel": "product", "method":"post", "href":"http://example.org/product/1"},
    {"rel": "product", "method":"put", "href":"http://example.org/product/1"}, ... 
]

Voilà, j’espère que cette petite initiation et explications aux API RESTful vous aura intéressé et donné envie de vous y mettre plus sérieusement. Peut-être changer un peu votre façon de coder, voire carrément changer de job pour trouver une équipe plus agile et plus au fait des pratiques de dev modernes. Et pourquoi pas en profiter pour continuer à évoluer dans les technologies, ou obtenir un meilleur salaire. C’est une démarche qui peut s’avérer assez compliquée, stressante parfois, tant on a envie de trouver un travail qui nous corresponde. On peut souhaiter avoir un travail plus proche de chez soi voire en télétravail complet, un meilleur salaire, une meilleure ambiance au travail, ou même tout ça à la fois (mais ce n’est pas forcément facile à trouver).

Heureusement, talent.io est là pour vous aider. Il vous suffit de créer un compte sur la plateforme talent.io en quelques clics pour ensuite recevoir des offres de la part d’entreprises qui correspondent à vos critères précis et qui affichent un salaire d’entrée de jeu. talent.io est vraiment le moyen le plus simple de trouver son prochain job tech, d’ailleurs les inscrits trouvent leur emploi en 20 jours en moyenne.

La police Londonienne annonce l’arrestation du pirate de GTA6 … mais !

Vendredi 23 septembre, la police londonienne annonce l'arrestation du présumé pirate de l'entreprise RockStar Games (GTA6). A-t-il agi seul ?...

How I Integrated Zapier into my Django Project

As you might know, I have been developing, providing, and supporting the prioritization tool 1st things 1st. One of the essential features to implement was exporting calculated priorities to other productivity tools. Usually, building an export from one app to another takes 1-2 weeks for me. But this time, I decided to go a better route and use Zapier to export priorities to almost all possible apps in a similar amount of time. Whaaat!?? In this article, I will tell you how.

What is Zapier and how it works?

The no-code tool Zapier takes input from a wide variety of web apps and outputs it to many other apps. Optionally you can filter the input based on conditions. Or format the input differently (for example, convert HTML to Markdown). In addition, you can stack the output actions one after the other. Usually, people use 2-3 steps for their automation, but there are power users who create 50-step workflows.

The input is managed by Zapier's triggers. The output is controlled by Zapier's actions. These can be configured at the website UI or using a command-line tool. I used the UI as this was my first integration. Trigger events accept a JSON feed of objects with unique IDs. Each new item there is treated as a new input item. With a free tier, the triggers are checked every 15 minutes. Multiple triggers are handled in parallel, and the sorting order of execution is not guaranteed. As it is crucial to have the sorting order correct for 1st things 1st priorities, people from Zapier support suggested providing each priority with a 1-minute interval to make sure the priorities get listed in the target app sequentially.

The most challenging part of Zapier integration was setting up OAuth 2.0 provider. Even though I used a third-party Django app django-oauth-toolkit for that. Zapier accepts other authentication options too, but this one is the least demanding for the end-users.

Authentication

OAuth 2.0 allows users of one application to use specific data of another application while keeping private information private. You might have used the OAuth 2.0 client directly or via a wrapper for connecting to Twitter apps. For Zapier, one has to set OAuth 2.0 provider.

The official tutorial for setting up OAuth 2.0 provider with django-oauth-toolkit is a good start. However, one problem with it is that by default, any registered user can create OAuth 2.0 applications at your Django website, where in reality, you need just one global application.

First of all, I wanted to allow OAuth 2.0 application creation only for superusers.

For that, I created a new Django app oauth2_provider_adjustments with modified views and URLs to use instead of the ones from django-oauth-toolkit.

The views related to OAuth 2.0 app creation extended this SuperUserOnlyMixin instead of LoginRequiredMixin:

from django.contrib.auth.mixins import AccessMixin

class SuperUserOnlyMixin(AccessMixin):
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            return self.handle_no_permission()
        return super().dispatch(request, *args, **kwargs)

Then I replaced the default oauth2_provider URLs:

urlpatterns = [
    # …
    path("o/", include("oauth2_provider.urls", namespace="oauth2_provider")),
]

with my custom ones:

urlpatterns = [
    # …
    path("o/", include("oauth2_provider_adjustments.urls", namespace="oauth2_provider")),
]

I set the new OAuth 2.0 application by going to /o/applications/register/ and filling in this info:

Name: Zapier
Client type: Confidential
Authorization grant type: Authorization code
Redirect uris: https://zapier.com/dashboard/auth/oauth/return/1stThings1stCLIAPI/ (copied from Zapier)
Algorithm: No OIDC support

If you have some expertise in the setup choices and see any flaws, let me know.

Zapier requires creating a test view that will return anything to check if there are no errors authenticating a user with OAuth 2.0. So I made a simple JSON view like this:

from django.http.response import JsonResponse


def user_info(request, *args, **kwargs):
    if not request.user.is_authenticated:
        return JsonResponse(
            {
                "error": "User not authenticated",
            },
            status=200,
        )
    return JsonResponse(
        {
            "first_name": request.user.first_name,
            "last_name": request.user.last_name,
        },
        status=200,
    )

Also, I had to have login and registration views for those cases when the user's session was not present.

Lastly, at Zapier, I had to set these values for OAuth 2.0:

Client ID: The Client ID from registered app
Client Secret: The Client Secret from registered app

Authorization URL: https://apps.1st-things-1st.com/o/authorize/
Scope: read write
Access Token Request: https://apps.1st-things-1st.com/o/token/
Refresh Token Request: https://apps.1st-things-1st.com/o/token/
I want to automatically refresh on unauthorized error: Checked
Test: https://apps.1st-things-1st.com/user-info/
Connection Label: {{first_name}} {{last_name}}

Trigger implementation

There are two types of triggers in Zapier:

  • (A) Ones for providing new things to other apps, for example, sending priorities from 1st things 1st to other productivity apps.
  • (B) Ones for listing things in drop boxes at the former triggers, for example, letting Zapier users choose the 1st things 1st project from which to import priorities.

The feeds for triggers should (ideally) be paginated. But without meta information for the item count, page number, following page URL, etc., you would usually have with django-rest-framework or other REST frameworks. Provide only an array of objects with unique IDs for each page. The only field name that matters is "id" – others can be anything. Here is an example:

[
    {
        "id": "39T7NsgQarYf",
        "project": "5xPrQbPZNvJv",
        "title": "01. Custom landing pages for several project types (83%)",
        "plain_title": "Custom landing pages for several project types",
        "description": "",
        "score": 83,
        "priority": 1,
        "category": "Choose"
    },
    {
        "id": "4wBSgq3spS49",
        "project": "5xPrQbPZNvJv",
        "title": "02. Zapier integration (79%)",
        "plain_title": "Zapier integration",
        "description": "",
        "score": 79,
        "priority": 2,
        "category": "Choose"
    },
    {
        "id": "6WvwwB7QAnVS",
        "project": "5xPrQbPZNvJv",
        "title": "03. Electron.js desktop app for several project types (42%)",
        "plain_title": "Electron.js desktop app for several project types",
        "description": "",
        "score": 41,
        "priority": 3,
        "category": "Consider"
    }
]

The feeds should list items in reverse order for the (A) type of triggers: the newest things go at the beginning. The pagination is only used to cut the number of items: the second and further pages of the paginated list are ignored by Zapier.

In my specific case of priorities, the order matters, and no items should be lost in the void. So I listed the priorities sequentially (not newest first) and set the number of items per page unrealistically high so that you basically get all the things on the first page of the feed.

The feeds for the triggers of (B) type are normally paginated from the first page until the page returns empty results. The order should be alphabetical, chronological, or by sorting order field, whatever makes sense. There you need just two fields, the ID and the title of the item (but more fields are allowed too), for example:

[
    {
        "id": "5xPrQbPZNvJv",
        "title": "1st things 1st",
        "owner": "Aidas Bendoraitis"
    },
    {
        "id": "VEXGzThxL6Sr",
        "title": "Make Impact",
        "owner": "Aidas Bendoraitis"
    },
    {
        "id": "WoqQbuhdUHGF",
        "title": "DjangoTricks website",
        "owner": "Aidas Bendoraitis"
    },
]

I used django-rest-framework to implement the API because of the batteries included, such as browsable API, permissions, serialization, pagination, etc.

For the specific Zapier requirements, I had to write a custom pagination class, SimplePagination, to use with my API lists. It did two things: omitted the meta section and showed an empty list instead of a 404 error for pages that didn't have any results:

from django.core.paginator import InvalidPage

from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response


class SimplePagination(PageNumberPagination):
    page_size = 20

    def get_paginated_response(self, data):
        return Response(data)  # <-- Simple pagination without meta

    def get_paginated_response_schema(self, schema):
        return schema  # <-- Simple pagination without meta

    def paginate_queryset(self, queryset, request, view=None):
        """
        Paginate a queryset if required, either returning a
        page object, or `None` if pagination is not configured for this view.
        """
        page_size = self.get_page_size(request)
        if not page_size:
            return None

        paginator = self.django_paginator_class(queryset, page_size)
        page_number = self.get_page_number(request, paginator)

        try:
            self.page = paginator.page(page_number)
        except InvalidPage as exc:
            msg = self.invalid_page_message.format(
                page_number=page_number, message=str(exc)
            )
            return []  # <-- If no items found, don't raise NotFound error

        if paginator.num_pages > 1 and self.template is not None:
            # The browsable API should display pagination controls.
            self.display_page_controls = True

        self.request = request
        return list(self.page)

To preserve the order of items, I had to make the priorities appear one by one at 1-minute intervals. I did that by having a Boolean field exported_to_zapier at the priorities. The API showed priorities only if that field was set to True, which wasn't the case by default. Then, background tasks were scheduled 1 minute after each other, triggered by a button click at 1st things 1st, which set the exported_to_zapier to True for each next priority. I was using huey, but the same can be achieved with Celery, cron jobs, or other background task manager:

# zapier_api/tasks.py
from django.conf import settings
from django.utils.translation import gettext
from huey.contrib.djhuey import db_task


@db_task()
def export_next_initiative_to_zapier(project_id):
    from evaluations.models import Initiative

    next_initiatives = Initiative.objects.filter(
        project__pk=project_id,
        exported_to_zapier=False,
    ).order_by("-total_weight", "order")
    count = next_initiatives.count()
    if count > 0:
        next_initiative = next_initiatives.first()
        next_initiative.exported_to_zapier = True
        next_initiative.save(update_fields=["exported_to_zapier"])

        if count > 1:
            result = export_next_initiative_to_zapier.schedule(
                kwargs={"project_id": project_id},
                delay=settings.ZAPIER_EXPORT_DELAY,
            )
            result(blocking=False)

One gotcha: Zapier starts pagination from 0, whereas django-rest-framework starts pagination from 1. To make them work together, I had to modify the API request (written in JavaScript) at Zapier trigger configuration:

const options = {
  url: 'https://apps.1st-things-1st.com/api/v1/projects/',
  method: 'GET',
  headers: {
    'Accept': 'application/json',
    'Authorization': `Bearer ${bundle.authData.access_token}`
  },
  params: {
    'page': bundle.meta.page + 1  // <-- The custom line for pagination
  }
}

return z.request(options)
  .then((response) => {
    response.throwForStatus();
    const results = response.json;

    // You can do any parsing you need for results here before returning them

    return results;
  });

Final Words

For the v1 of Zapier integration, I didn't need any Zapier actions, so they are yet something to explore, experiment with, and learn about. But the Zapier triggers seem already pretty helpful and a big win compared to individual exports without this tool.

If you want to try the result, do this:

  • Create an account and a project at 1st things 1st
  • Prioritize something
  • Head to Zapier integrations and connect your prioritization project to a project of your favorite to-do list or project management app
  • Then click on "Export via Zapier" at 1st things 1st.

Cover photo by Anna Nekrashevich

Raspberry Pi helped restore this boat to former glory


Baltic is a handsome 1962 vintage tugboat that was built in Norway, where she operated until the 1980s. She’s now in English waters, having been registered in Southampton once renovations were complete. After some initial hull restoration work in France she sailed to the western Ligurian coast in Italy, where it took about five years to complete the work. The boat’s original exterior was restored, while the inside was fully refurbished to the standard of a luxury yacht.

restored boat being pulled out of water before any work had been done on it
You need quite a large crane to do this

But where is the Raspberry Pi?

Ulderico Arcidiaco, who coordinated the digital side of Baltic’s makeover, is the CEO of Sfera Labs, so naturally he turned to Raspberry Pi Compute Module 3+ in the guise of Sfera’s Strato Pi CM Duo for the new digital captain of the vessel.

Strato Pi CM Duo is an industrial server comprising a Raspberry Pi Compute Module 3+ inside a DIN-rail case with a slew of additional features. The MagPi magazine took a good look at them when they launched.

restored boat control room
Beats the view from our windows

The Strato Pi units are the four with red front panels in the cabinet pictured below. There are four other Raspberry Pi Compute Modules elsewhere onboard. Two are identical to the Strato Pi CM Duos in this photo; another is inside an Iono Pi Max; and there’s a Compute Module 4 inside an Exo Sense Pi down in the galley.

restored boat control cupboard
No spaghetti here

Thoroughly modern makeover

Baltic now has fully integrated control of all core and supplementary functions, from power distribution to tanks and pump control, navigation, alarms, fire, lighting, stabilisers, chargers, inverters, battery banks, and video. All powered by Raspberry Pi.

restored boat docked in sunny blue sky location
What a beauty

Ulderico says:

“When it was built sixty years ago, not even the wildest science fiction visionary could have imagined she would one day be fully computer controlled, and not by expensive dedicated computer hardware, but by a tiny and inexpensive device that any kid can easily buy and play with to have fun learning.

And, if there is some old-fashioned patriotism in things, the Raspberry Pi on board will surely like the idea of being back under their home British Flag.”

The post Raspberry Pi helped restore this boat to former glory appeared first on Raspberry Pi.

Raspberry Pi listening posts ‘hear’ the Borneo rainforest

These award-winning, solar-powered audio recorders, built on Raspberry Pi, have been installed in the Borneo rainforest so researchers can listen to the local ecosystem 24/7. The health of a forest ecosystem can often be gaged according to how much noise it creates, as this signals how many species are around.

And you can listen to the rainforest too! The SAFE Acoustics website, funded by the World Wide Fund for Nature (WWF), streams audio from recorders placed around a region of the Bornean rainforest in Southeast Asia. Visitors can listen to live audio or skip back through the day’s recording, for example to listen to the dawn chorus.

Listen in on the Imperial College podcast

What’s inside?

We borrowed this image of the flux tower from Sarab Sethi’s site

The device records data in the field and uploads it to a central server continuously and robustly over long time-periods. And it was built for around $305.

Here’s all the code for the platform, on GitHub.

The 12V-to-5V micro USB converter to the power socket of the Anker USB hub, which is connected to Raspberry Pi.

The Imperial College London team behind the project has provided really good step-by-step photo instructions for anyone interested in the fine details.

Here’s the full set up in the field. The Raspberry Pi-powered brains of the kit are safely inside the green box

The recorders have been installed by Imperial College London researchers as part of the SAFE Project – one of the largest ecological experiments in the world.

Screenshot of the SAFE Project website

Dr Sarab Sethi designed the audio recorders with Dr Lorenzo Picinali. They wanted to quantify the changes in rainforest soundscape as land use changes, for example when forests are logged. Sarab is currently working on algorithms to analyse the gathered data with Dr Nick Jones from the Department of Mathematics.

The lovely cross-disciplinary research team based at Imperial College London

Let the creators of the project tell you more on the Imperial College London website.

The post Raspberry Pi listening posts ‘hear’ the Borneo rainforest appeared first on Raspberry Pi.

Nginx upstream sent too big header while reading response header from upstream

Par : Vivek Gite

Nginx upstream sent too big header while reading response header from upstream

I am getting the following error and my app stops working:
    2020/07/12 14:32:03 [error] 45625#45625: *10918 upstream sent too big header while reading response header from upstream, client: 139.xxx.yyy.zzz, server: www.nixcraft.com, request: "POST /app/mg/posts HTTP/2.0", upstream: "fastcgi://unix:/run/php/php-fpm.sock:", host: "www.nixcraft.com", referrer: "https://www.nixcraft.com/mg/admin/index.app"
How do I fix this error for Nginx web server running on Linux or Unix-like systems?

The post Nginx upstream sent too big header while reading response header from upstream appeared first on nixCraft.

❌