Recherche des tweets de réponse avec l'API Tweeter

This commit is contained in:
hugol
2024-11-17 13:55:25 +01:00
parent 3d386178bf
commit 8dc18553ec
1751 changed files with 379552 additions and 0 deletions

View File

@@ -0,0 +1,557 @@
<?php
namespace App\Http\Controllers;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Subscriber\Oauth\Oauth1;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
class APIController extends Controller
{
protected $twitterHeaders = [
'User-Agent' => 'TwitterAndroid/10.46.0-release.0 (310460000-r-0) Android+SDK+built+for+x86/11 (unknown;Android+SDK+built+for+x86;Android;sdk_phone_x86;0;;1;2013)',
'x-twitter-client-language' => 'en-US',
'x-twitter-client-version' => '10.46.0-release.0',
'x-twitter-client' => 'TwitterAndroid',
'x-twitter-api-version' => '5',
'x-twitter-active-user' => 'yes',
'os-version' => '30',
'x-attest-token' => 'no_token',
];
public function retweet($user, $tweetid)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/graphql/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
$params = [
"features" => json_encode([
"longform_notetweets_inline_media_enabled" => true,
"super_follow_badge_privacy_enabled" => true,
"longform_notetweets_rich_text_read_enabled" => true,
"super_follow_user_api_enabled" => true,
"super_follow_tweet_api_enabled" => true,
"articles_api_enabled" => true,
"android_graphql_skip_api_media_color_palette" => true,
"creator_subscriptions_tweet_preview_api_enabled" => true,
"freedom_of_speech_not_reach_fetch_enabled" => true,
"tweetypie_unmention_optimization_enabled" => true,
"longform_notetweets_consumption_enabled" => true,
"subscriptions_verification_info_enabled" => true,
"blue_business_profile_image_shape_enabled" => true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled" => true,
"immersive_video_status_linkable_timestamps" => true,
"super_follow_exclusive_tweet_notifications_enabled" => true,
]),
"variables" => json_encode([
"includeTweetImpression" => true,
"includeHasBirdwatchNotes" => false,
"includeEditPerspective" => false,
"tweet_id" => $tweetid,
"includeEditControl" => true,
"includeTweetVisibilityNudge" => true,
])
];
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->post('24zITFB5aD73PxYtmc6pkA/CreateRetweet', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth',
'json' => $params
]);
if ($res->getStatusCode() != 200) {
$text = "Le compte twitter ".$user->Name." a été désactivé";
Http::get('https://api.telegram.org/bot7036172799:AAEVZXHu4SL64VWN5c0AxM1BVxvB0-k6lT0/sendMessage?chat_id=1970698501&text=' . urlencode($text));
$user->enabled = false;
$user->save();
}
}
public function reply($user, $tweetid, $text)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/graphql/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
$params = [
"features" => json_encode([
"longform_notetweets_inline_media_enabled" => true,
"super_follow_badge_privacy_enabled" => true,
"longform_notetweets_rich_text_read_enabled" => true,
"super_follow_user_api_enabled" => true,
"super_follow_tweet_api_enabled" => true,
"articles_api_enabled" => true,
"android_graphql_skip_api_media_color_palette" => true,
"creator_subscriptions_tweet_preview_api_enabled" => true,
"freedom_of_speech_not_reach_fetch_enabled" => true,
"tweetypie_unmention_optimization_enabled" => true,
"longform_notetweets_consumption_enabled" => true,
"subscriptions_verification_info_enabled" => true,
"blue_business_profile_image_shape_enabled" => true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled" => true,
"immersive_video_status_linkable_timestamps" => true,
"super_follow_exclusive_tweet_notifications_enabled" => true
]),
"variables" => json_encode([
"nullcast" => false,
"includeTweetImpression" => true,
"includeHasBirdwatchNotes" => false,
"includeEditPerspective" => false,
"includeEditControl" => true,
"batch_compose" => "BatchSubsequent",
"includeCommunityTweetRelationship" => false,
"reply" => [
"exclude_reply_user_ids" => [],
"in_reply_to_tweet_id" => $tweetid,
],
"includeTweetVisibilityNudge" => true,
"tweet_text" => $text,
]),
];
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->post('2ambiU1P_BmZ_CZ1yQ8E1Q/CreateTweet', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth',
'json' => $params
]);
if ($res->getStatusCode() != 200) {
$text = "Le compte twitter ".$user->Name." a été désactivé";
Http::get('https://api.telegram.org/bot7036172799:AAEVZXHu4SL64VWN5c0AxM1BVxvB0-k6lT0/sendMessage?chat_id=1970698501&text=' . urlencode($text));
$user->enabled = false;
$user->save();
}
}
public function follow($user, $follow)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/1.1/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->post('friendships/create.json?screen_name='.$follow.'&follow=true', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth' // Assurez-vous que l'authentification OAuth est incluse
]);
if ($res->getStatusCode() != 200) {
$text = "Le compte twitter ".$user->Name." a été désactivé";
Http::get('https://api.telegram.org/bot7036172799:AAEVZXHu4SL64VWN5c0AxM1BVxvB0-k6lT0/sendMessage?chat_id=1970698501&text=' . urlencode($text));
$user->enabled = false;
$user->save();
}
}
public function like($user, $tweetid)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/graphql/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
$params = [
"variables" => [
"includeTweetImpression" => true,
"includeHasBirdwatchNotes" => false,
"includeEditPerspective" => false,
"tweet_id" => $tweetid,
"includeEditControl" => true
]
];
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->post('lI07N6Otwv1PhnEgXILM7A/FavoriteTweet', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth',
'json' => $params
]);
}
public function tweet($user, $text)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/graphql/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
$params = [
"features" => [
"longform_notetweets_inline_media_enabled" => true,
"super_follow_badge_privacy_enabled" => true,
"longform_notetweets_rich_text_read_enabled" => true,
"super_follow_user_api_enabled" => true,
"super_follow_tweet_api_enabled" => true,
"articles_api_enabled" => true,
"android_graphql_skip_api_media_color_palette" => true,
"creator_subscriptions_tweet_preview_api_enabled" => true,
"freedom_of_speech_not_reach_fetch_enabled" => true,
"tweetypie_unmention_optimization_enabled" => true,
"longform_notetweets_consumption_enabled" => true,
"subscriptions_verification_info_enabled" => true,
"blue_business_profile_image_shape_enabled" => true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled" => true,
"immersive_video_status_linkable_timestamps" => true,
"super_follow_exclusive_tweet_notifications_enabled" => true
],
"variables" => [
"nullcast" => false,
"includeTweetImpression" => true,
"includeHasBirdwatchNotes" => false,
"includeEditPerspective" => false,
"includeEditControl" => true,
"includeCommunityTweetRelationship" => false,
"includeTweetVisibilityNudge" => true,
"tweet_text" => $text
]
];
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->post('2ambiU1P_BmZ_CZ1yQ8E1Q/CreateTweet', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth',
'json' => $params
]);
}
public function unread($user)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/2/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->get('badge_count/badge_count.json?supports_ntab_urt=true', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth' // Assurez-vous que l'authentification OAuth est incluse
]);
$unred = json_decode($res->getBody()->getContents(), true);
// L'URL des deux liens
$url = 'https://myx.ovh/nova/resources/accounts/'.$user->id;
$keyboard = [
'inline_keyboard' => [
[
['text' => 'Cliquez ici pour plus d\'infos', 'url' => $url]
]
]
];
// Convertir le tableau de clavier en JSON
$keyboardJson = json_encode($keyboard);
if ($unred['dm_unread_count'] > 0) {
$text = "Un nouveau message pour le compte ".$user->name;
Http::get('https://api.telegram.org/bot6784810105:AAEq3emnkRwdyvCLC-iqdIjVJ2Ke6HwwGjg/sendMessage', [
'chat_id' => '1970698501', // Remplacez par votre chat_id
'text' => $text,
'reply_markup' => $keyboardJson
]);
}elseif ($unred['ntab_unread_count'] > 0) {
$text = "Une notification pour le compte ".$user->name;
Http::get('https://api.telegram.org/bot6784810105:AAEq3emnkRwdyvCLC-iqdIjVJ2Ke6HwwGjg/sendMessage', [
'chat_id' => '1970698501', // Remplacez par votre chat_id
'text' => $text,
'reply_markup' => $keyboardJson
]);
}
}
public function getweets($user, $tweetid)
{
$stack = $this->Oauth1($user);
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/graphql/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
$params = [
'variables' => [
'referrer' => 'home',
'includeTweetImpression' => true,
'includeHasBirdwatchNotes' => false,
'isReaderMode' => false,
'includeEditPerspective' => false,
'includeEditControl' => true,
'focalTweetId' => $tweetid,
'includeCommunityTweetRelationship' => true,
'includeTweetVisibilityNudge' => true
],
'features' => [
'longform_notetweets_inline_media_enabled' => true,
'super_follow_badge_privacy_enabled' => true,
'longform_notetweets_rich_text_read_enabled' => true,
'super_follow_user_api_enabled' => true,
'unified_cards_ad_metadata_container_dynamic_card_content_query_enabled' => true,
'super_follow_tweet_api_enabled' => true,
'articles_api_enabled' => true,
'android_graphql_skip_api_media_color_palette' => true,
'creator_subscriptions_tweet_preview_api_enabled' => true,
'freedom_of_speech_not_reach_fetch_enabled' => true,
'tweetypie_unmention_optimization_enabled' => true,
'longform_notetweets_consumption_enabled' => true,
'subscriptions_verification_info_enabled' => true,
'blue_business_profile_image_shape_enabled' => true,
'tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled' => true,
'immersive_video_status_linkable_timestamps' => true,
'super_follow_exclusive_tweet_notifications_enabled' => true
]
];
// Initialisation du tableau des tweets à l'extérieur de la boucle
$tweets = [];
// Initialisation du curseur à null avant le début de la boucle
$cursor = null;
// Nombre de tours
$maxLoops = 10;
// Boucle pour exécuter 5 tours
for ($loop = 1; $loop <= $maxLoops; $loop++) {
// Si ce n'est pas le premier tour, ajouter le curseur dans les paramètres
if ($loop > 1 && $cursor !== null) {
$params['variables']['cursor'] = $cursor; // Ajouter la valeur du curseur au paramètre
}
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->get('NAHO_rBo3Yf1hBXROp7Msg/ConversationTimelineV2', [
'headers' => $this->twitterHeaders, // Ajouter les en-têtes ici
'auth' => 'oauth',
'json' => $params
]);
// Décoder la réponse
$data = json_decode($res->getBody()->getContents(), true);
// Réinitialiser le curseur à chaque tour
$cursor = null;
// Navigation dans le tableau pour extraire les données
$instructions = $data['data']['timeline_response']['instructions'] ?? [];
foreach ($instructions as $instruction) {
// Vérification si l'instruction est de type 'TimelineAddEntries'
if ($instruction['__typename'] === 'TimelineAddEntries') {
// Parcours des entrées (entries) dans chaque instruction
foreach ($instruction['entries'] as $entry) {
// Vérifier si l'entrée contient un tweet
if (isset($entry['content']['items'][0]['item']['content']['tweetResult'])) {
// Récupérer le texte complet du tweet
$tweets[] = $entry['content']['items'][0]['item']['content']['tweetResult']['result']['legacy']['full_text'] ?? '';
}
// Vérifier si l'entrée contient un curseur, dont l'entryId commence par 'cursor-bottom'
if (isset($entry['content']['content']['value']) && str_starts_with($entry['entryId'], 'cursor-bottom')) {
// Récupérer la valeur du curseur
$cursor = $entry['content']['content']['value'];
}
}
}
}
}
return $tweets;
}
public function newstweet($user)
{
$stack = $this->Oauth1($user);
$newArray = [];
$existingConversationIds = []; // Tableau pour suivre les IDs de conversation déjà vus
$search = [
'1177177387475378177',
'1491472590891888645',
'1642170070351638534',
'1533089245576970240',
'1493931667731406848',
'1513789977938776070',
'1531291630040391682',
'1741188576845455676'
];
foreach ($search as $list) {
// Créer le client Guzzle avec le handler stack
$client = new Client([
'base_uri' => 'https://api.twitter.com/graphql/',
'handler' => $stack,
'proxy' => [
'http' => 'http://xtjnmwvl-'.$user->id.':lp7iv1lq9glu@p.webshare.io:80',
]
]);
// Ajouter les en-têtes personnalisés
$headers = [
'User-Agent' => 'TwitterAndroid/10.46.0-release.0 (310460000-r-0) Android+SDK+built+for+x86/11 (unknown;Android+SDK+built+for+x86;Android;sdk_phone_x86;0;;1;2013)',
'x-twitter-client-language' => 'en-US',
'x-twitter-client-version' => '10.46.0-release.0',
'x-twitter-client' => 'TwitterAndroid',
'x-twitter-api-version' => '5',
'x-twitter-active-user' => 'yes',
'os-version' => '30',
'x-attest-token' => 'no_token',
];
$params = [
"features" => [
"longform_notetweets_inline_media_enabled" => true,
"super_follow_badge_privacy_enabled" => true,
"longform_notetweets_rich_text_read_enabled" => true,
"super_follow_user_api_enabled" => true,
"unified_cards_ad_metadata_container_dynamic_card_content_query_enabled" => true,
"super_follow_tweet_api_enabled" => true,
"articles_api_enabled" => true,
"android_graphql_skip_api_media_color_palette" => true,
"creator_subscriptions_tweet_preview_api_enabled" => true,
"freedom_of_speech_not_reach_fetch_enabled" => true,
"tweetypie_unmention_optimization_enabled" => true,
"longform_notetweets_consumption_enabled" => true,
"subscriptions_verification_info_enabled" => true,
"blue_business_profile_image_shape_enabled" => true,
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled" => true,
"immersive_video_status_linkable_timestamps" => true,
"super_follow_exclusive_tweet_notifications_enabled" => true,
],
"variables" => [
"includeTweetImpression" => true,
"includeHasBirdwatchNotes" => false,
"includeEditPerspective" => false,
"includeEditControl" => true,
"rest_id" => $list,
"includeTweetVisibilityNudge" => true,
]
];
// Effectuer la requête POST avec OAuth et les en-têtes personnalisés
$res = $client->get('LgWGBhvCVo5vHMsokMdEWA/ListTimeline', [
'headers' => $headers, // Ajouter les en-têtes ici
'auth' => 'oauth',
'json' => $params
]);
$data = json_decode($res->getBody()->getContents(), true);
$tweets = $data['data']['list']['timeline_response']['timeline']['instructions'][0]['entries'];
foreach ($tweets as $item) {
if (isset($item['content']['content']['tweetResult']['result']['legacy']['retweeted_status_result'])) {
// Tweet retweeté, ignorer
} elseif (isset($item['content']['content']['tweetResult']['result']['legacy'])) {
$news = $item['content']['content']['tweetResult']['result']['legacy'];
$conversationId = $news['conversation_id_str'];
// Vérifier si le tweet a déjà été ajouté en fonction de l'ID de la conversation
if (in_array($conversationId, $existingConversationIds)) {
continue; // Si le tweet existe déjà, passer à l'itération suivante
}
// Ajouter l'ID de conversation à la liste des IDs déjà vus
$existingConversationIds[] = $conversationId;
// Ajouter le tweet si le nombre de réponses, de favoris ou de retweets est supérieur à 50
if ($news['reply_count'] > 10 || $news['favorite_count'] > 10 || $news['retweet_count'] > 10) {
$newArray[] = $news;
}
}
}
}
Cache::put('news', $newArray, 1800);
return $newArray;
}
private function Oauth1($user)
{
// Créer le stack pour gérer l'authentification OAuth
$stack = HandlerStack::create();
$middleware = new Oauth1([
'consumer_key' => '3nVuSoBZnx6U4vzUxf5w',
'consumer_secret' => 'Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys',
'token' => $user->oauth_token,
'token_secret' => $user->oauth_token_secret
]);
$stack->push($middleware);
return $stack;
}
}

View File

@@ -0,0 +1,341 @@
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessNews;
use App\Models\Account;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
use App\Http\Controllers\APIController;
use Illuminate\Support\Facades\Cache;
use Webklex\PHPIMAP\ClientManager;
class AccountController extends Controller
{
public function login($id)
{
$user = Account::find($id);
$username = $user->name;
$password = $user->password;
$email = $user->rambler_email;
$rambler_password = $user->rambler_password;
$proxy = 'http://xtjnmwvl-'.$id.':lp7iv1lq9glu@p.webshare.io:80';
// Clés et jetons de Twitter
$TW_CONSUMER_KEY = '3nVuSoBZnx6U4vzUxf5w';
$TW_CONSUMER_SECRET = 'Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys';
$TW_ANDROID_BASIC_TOKEN = 'Basic ' . base64_encode("$TW_CONSUMER_KEY:$TW_CONSUMER_SECRET");
// Requête pour obtenir le bearer token
$response = Http::withHeaders([
'Authorization' => $TW_ANDROID_BASIC_TOKEN,
'Content-Type' => 'application/x-www-form-urlencoded',
])->asForm()->post('https://api.twitter.com/oauth2/token', [
'grant_type' => 'client_credentials',
]);
$bearerToken = collect($response->json())->implode(' ');
// Requête pour obtenir le guest token
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.twitter.com/1.1/guest/activate.json',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array(
'Authorization: ' . $bearerToken
),
));
$response = curl_exec($curl);
curl_close($curl);
$reponse = json_decode($response, true);
$guestToken = $reponse['guest_token'];
// Configuration des en-têtes pour les futures requêtes
$twitterHeaders = [
'Authorization' => $bearerToken,
'User-Agent' => 'TwitterAndroid/10.46.0-release.0 (310460000-r-0) Android+SDK+built+for+x86/11 (unknown;Android+SDK+built+for+x86;Android;sdk_phone_x86;0;;1;2013)',
'x-twitter-api-version' => '5',
'x-twitter-client' => 'TwitterAndroid',
'x-twitter-client-version' => '10.46.0-release.0',
'x-twitter-active-user' => 'yes',
'os-version' => '30',
'x-twitter-client-language' => 'en-US',
'x-attest-token' => 'no_token',
'X-Guest-Token' => $guestToken,
];
// Initialisation de la session avec Laravel HTTP pour le flux de connexion
// Étape 1 : Commencer le flux de connexion
$task1 = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json?flow_name=login&api_version=1&known_device_token=', [
'input_flow_data' => [
'country_code' => null,
'flow_context' => [
'start_location' => [
'location' => 'deeplink',
],
],
'requested_variant' => null,
'target_user_id' => 0,
],
]);
// Stockage de l'en-tête 'att' pour les futures requêtes
$twitterHeaders['att'] = $task1->header('att');
sleep(5);
// Étape 2 : Saisie du nom d'utilisateur
$task2 = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json', [
'flow_token' => $task1->json()['flow_token'],
'subtask_inputs' => [
[
'enter_text' => [
'text' => $username,
'link' => 'next_link',
],
'subtask_id' => 'LoginEnterUserIdentifier',
],
],
]);
sleep(5);
if ($task2->json()['subtasks'][0]['subtask_id'] === 'LoginEnterAlternateIdentifierSubtask') {
$task2bis = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json', [
'flow_token' => $task2->json()['flow_token'],
'subtask_inputs' => [
[
'enter_text' => [
'text' => $email,
'link' => 'next_link',
],
'subtask_id' => 'LoginEnterAlternateIdentifierSubtask',
],
],
]);
$task2 = $task2bis;
}
sleep(5);
// Étape 3 : Saisie du mot de passe
$task3 = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json', [
'flow_token' => $task2->json()['flow_token'],
'subtask_inputs' => [
[
'enter_password' => [
'password' => $password,
'link' => 'next_link',
],
'subtask_id' => 'LoginEnterPassword',
],
],
]);
if ($task3->json()['subtasks'][0]['subtask_id'] === 'LoginAcid') {
sleep(5);
if(isset($task3->json()['subtasks'][0]['enter_text']['hint_text'])){
$code = $this->getCodeFromLastEmail($email, $rambler_password);
$task3bis = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json', [
'flow_token' => $task3->json()['flow_token'],
'subtask_inputs' => [
[
'enter_text' => [
'text' => $code,
'link' => 'next_link',
],
'subtask_id' => 'LoginAcid',
],
],
]);
}else{
$task3bis = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json', [
'flow_token' => $task3->json()['flow_token'],
'subtask_inputs' => [
[
'enter_text' => [
'text' => $email,
'link' => 'next_link',
],
'subtask_id' => 'LoginAcid',
],
],
]);
}
$task3 = $task3bis;
}
if($task3->json()['subtasks'][0]['subtask_id'] === 'LoginEnterOtp'){
$code = $this->getCodeFromLastEmail($email, $rambler_password);
$task3bis = Http::withOptions([
'proxy' => $proxy
])->withHeaders($twitterHeaders)->post('https://api.twitter.com/1.1/onboarding/task.json', [
'flow_token' => $task3->json()['flow_token'],
'subtask_inputs' => [
[
'enter_text' => [
'text' => $code,
'link' => 'next_link',
],
'subtask_id' => 'LoginEnterOtp',
],
],
]);
$task3 = $task3bis;
}
if($task3->json()['subtasks']['0']['subtask_id'] == 'LoginSuccessSubtask' ){
$user->update([
'oauth_token' => $task3->json()['subtasks']['0']['open_account']['oauth_token'],
'oauth_token_secret' => $task3->json()['subtasks']['0']['open_account']['oauth_token_secret'],
'known_device_token' => $task3->json()['subtasks']['0']['open_account']['known_device_token'],
'enable' => true,
]);
return true;
}else{
return false;
}
}
private function getCodeFromLastEmail($email, $password)
{
// Attendre 15 secondes avant de vérifier les emails
sleep(15);
// Configurer le client IMAP de manière dynamique
$clientManager = new ClientManager();
$client = $clientManager->make([
'host' => 'imap.rambler.ru',
'port' => '993',
'encryption' => 'ssl',
'validate_cert' => true,
'username' => $email,
'password' => $password,
'protocol' => 'imap'
]);
// Se connecter au compte
$client->connect();
// Sélectionner la boîte de réception
$folder = $client->getFolder('INBOX');
// Récupérer le dernier email de l'expéditeur "verify@x.com"
$messages = $folder->messages()->all()->get();
$count = count($messages);
$message = $messages[$count - 1];
if ($message) {
// Vérifier le titre de l'email
$subject = $message->getSubject();
// Chercher le code dans le sujet
if (preg_match('/Your X confirmation code is (\w+)/', $subject, $matches)) {
return $matches[1]; // Retourner le code trouvé dans le titre
}
// Si aucun code trouvé dans le sujet, vérifier le corps du mail
$body = $message->getTextBody();
if (preg_match('/\b(\d{6})\b/', $body, $matches)) {
return $matches[1]; // Retourner le code trouvé dans le corps
}
}
return null;
}
public function tweetnews()
{
// Vérifier si la queue est vide (en fonction de votre driver)
$queue = Queue::getDefaultDriver(); // Par défaut, c'est 'default'
$jobsCount = Queue::size($queue);
if ($jobsCount === 0) {
$accounts = Account::where('enable', true)->get();
foreach($accounts as $user){
$API = new APIController();
//On check les notifs
$API->unread($user);
if (Cache::has('news')) {
$news = Cache::get('news');
}else{
$news = $API->newstweet($user);
}
shuffle($news);
$nb = rand(1,3);
if (count($news) >= $nb) {
$selectedArticles = array_slice($news, 0, $nb);
foreach ($selectedArticles as $article) {
$tweetid = $article['conversation_id_str'];
$API->retweet($user, $tweetid);
sleep(15);
}
}
}
}
}
public
function auto($contestId)
{
$contest = Contest::find($contestId);
if (!$contest) {
session()->flash('error', 'Concours introuvable.');
return;
}
flash()->success('Concours ' . $contest->name . ' en cours de participation');
// Récupération des comptes activés
$accounts = Account::where('enable', true)->get();
foreach ($accounts as $account) {
ProcessTweet::dispatch($contest->id, $account->id); // Envoi du tweet pour participer
}
// Mise à jour du concours pour indiquer qu'il a été participé
$contest->participated = true;
$contest->save();
// Recharger les concours
$this->resetPage(); // Reset pagination to the first page
}
}

View File

@@ -0,0 +1,118 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\TwitterController;
use App\Models\Account;
use App\Models\Block;
use App\Models\Concour;
use App\Models\Contest;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Laravel\Dusk\Browser;
use Symfony\Component\BrowserKit\HttpBrowser;
use Symfony\Component\HttpClient\HttpClient;
use Illuminate\Http\Request;
use Throwable;
class BotController extends Controller
{
public function getSpecialComment($user,$id){
$user = Account::find($user);
$API = new APIController();
// On check les notifs
$texts = $API->getweets($user, $id);
// Filtrer les phrases vides
$texts = array_filter($texts, function($phrase) {
return !empty(trim($phrase)); // Ignore les chaînes vides ou contenant uniquement des espaces
});
// Initialiser un tableau pour stocker les occurrences des phrases
$occurrences = [];
foreach ($texts as $index1 => $phrase1) {
foreach ($texts as $index2 => $phrase2) {
if ($index1 !== $index2) {
$similarity = $this->cosineSimilarity($phrase1, $phrase2);
// Vous pouvez ajuster le seuil de similarité en fonction de vos besoins
if ($similarity > 0.5) {
// Incrémenter le compteur pour les deux phrases
$occurrences[$index1] = isset($occurrences[$index1]) ? $occurrences[$index1] + 1 : 1;
$occurrences[$index2] = isset($occurrences[$index2]) ? $occurrences[$index2] + 1 : 1;
}
}
}
}
// Trouver l'index de la phrase avec le comptage le plus élevé
$indexPhrasePlusFrequente = (!empty($occurrences)) ? array_search(max($occurrences), $occurrences) : null;
// Récupérer la phrase avec le comptage le plus élevé
$phrasePlusFrequente = ($indexPhrasePlusFrequente !== null) ? $texts[$indexPhrasePlusFrequente] : null;
if ($phrasePlusFrequente != null) {
// Supprimer les hashtags
$phrasePlusFrequente = preg_replace('/#\w+\s?/', '', $phrasePlusFrequente);
// Supprimer les tags
$phrasePlusFrequente = preg_replace('/@\w+\s?/', '', $phrasePlusFrequente);
// Supprimer les emojis
$phrasePlusFrequente = $this->remove_emojis($phrasePlusFrequente);
return $phrasePlusFrequente;
} else {
$tweetcomments = config('twitter.sentence_for_random_comment');
return Arr::random($tweetcomments);
}
}
private function cosineSimilarity($text1, $text2)
{
$words1 = str_word_count(strtolower($text1), 1);
$words2 = str_word_count(strtolower($text2), 1);
$allWords = array_unique(array_merge($words1, $words2));
$vector1 = $vector2 = [];
// Construire les vecteurs avec les fréquences des mots
foreach ($allWords as $word) {
$vector1[] = in_array($word, $words1) ? 1 : 0;
$vector2[] = in_array($word, $words2) ? 1 : 0;
}
$dotProduct = 0;
// Calculer le produit scalaire des vecteurs
for ($i = 0; $i < count($allWords); $i++) {
$dotProduct += $vector1[$i] * $vector2[$i];
}
$magnitude1 = sqrt(array_sum($vector1));
$magnitude2 = sqrt(array_sum($vector2));
if ($magnitude1 * $magnitude2 == 0) {
return 0; // Pour éviter une division par zéro
}
return $dotProduct / ($magnitude1 * $magnitude2);
}
private function remove_emojis($string)
{
// Match all emojis (including extended ones)
$regex_emojis = '/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u';
$clear_string = preg_replace($regex_emojis, '', $string);
return $clear_string;
}
}

View File

@@ -0,0 +1,521 @@
<?php
namespace App\Http\Controllers;
use App\Models\Block;
use App\Models\Contest;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Symfony\Component\BrowserKit\HttpBrowser;
use Symfony\Component\HttpClient\HttpClient;
class ContestController extends Controller
{
public function twitterlist()
{
$client = new HttpBrowser(HttpClient::create(['verify_peer' => false, 'verify_host' => false, 'timeout' => '60']));
// Création des informations d'authentification
$username = 'MyX';
$password = '@Gaudin95';
$credentials = base64_encode("$username:$password");
// Ajout des informations d'authentification à l'en-tête de la demande HTTP
$client->setServerParameter('HTTP_AUTHORIZATION', 'Basic ' . $credentials);
$client->setServerParameter('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36');
$crawler = $client->request('GET', 'https://nitter-myx.fly.dev/i/lists/1686126753205387264');
$i = 1;
while ($i < 50){
$results = $crawler->filterXPath('//div[@class="timeline-item "]')->each(function ($node) {
$id = ($node->filterXPath('//*[@class="tweet-link"]'))->attr('href');
$created_at = ($node->filterXPath('//span[@class="tweet-date"]/a'))->attr('title');
$text = ($node->filterXPath('//*[@class="tweet-content media-body"]'))->text();
$screen = ($node->filterXPath('//a[@class="username"]'))->text();
$fullname = ($node->filterXPath('//a[@class="fullname"]'))->text();
$imageNode = $node->filterXPath('//a[@class="still-image"]');
$nbretweet = ($node->filterXPath('//*[@class="tweet-stat"][2]'))->text();
$nbretweet = str_replace(',', '', $nbretweet);
$nblike = ($node->filterXPath('//*[@class="tweet-stat"][4]'))->text();
$nblike = str_replace(',', '', $nblike);
$nbreply = ($node->filterXPath('//*[@class="tweet-stat"][1]'))->text();
$nbreply = str_replace(',', '', $nbreply);
//Modifications
if ($imageNode->count() > 0) {
$picture = $imageNode->attr('href');
$picture = urldecode($picture);
$picture = str_replace('/pic/orig/', 'https://pbs.twimg.com/', $picture);
}else{
$picture = null;
}
$screen = str_replace('@', '', $screen);
$id = str_replace('/'.$screen.'/status/', '', $id);
$id = str_replace('#m', '', $id);
$contest = Contest::where('tweetid', $id)->first();
$fake = Block::where('screen_name', $screen)->first();
$containsBlacklistedWord = preg_match('/' . implode('|', array_map('preg_quote', config('twitter.giveaway_to_blacklist'), ['/'])) . '/i', $text) === 1;
if(!$contest && !$fake && $nbretweet > 100 && $containsBlacklistedWord !== true) {
$regex_detect_rts =
[
"/\bRT\b/",
"/RETWEET/i",
"/REPUBL/i",
"/REPOST/i",
];
foreach ($regex_detect_rts as $regex_detect_rt) {
//if (strstr($string, $url)) { // mine version
preg_match($regex_detect_rt, $text, $invites);
if (isset($invites[0])) {
$rt = true;
}
}
//On verifie que si RT
if (isset($rt)) {
$inputs = array();
//On recherche la date de fin du concours
$date = $this->getDate($text);
if ($date != null) {
$fin = $date;
} else {
$fin = $this->getTwitterDate($created_at);
}
//On recherche la date de fin du concours
if ($fin >= Carbon::now()->format('Y-m-d')) {
Contest::create([
'name' => $fullname,
'screen' => $screen,
'description' => $text,
'url' => 'https://x.com/'.$screen.'/status/'.$id,
'picture' => $picture,
'tweetid' => $id,
'fin' => $fin,
'nbretweet' => $nbretweet,
'nblike' => $nblike,
'nbreply' => $nbreply,
]);
}
}
}
});
$nextPageButton = $crawler->filterXPath('//div[@class="show-more"]/a')->link();
$url = $nextPageButton->getUri();
$crawler = $client->request('GET', $url);
$i++;
}
$reponse = $client->getResponse();
var_dump($reponse);
echo 'Fait !';
}
public function searchcontest()
{
$search = [
'giveaway',
'#concours',
'concours like',
'concours rt',
'concours follow',
'#JeuConcours',
'JeuConcours',
'jeu concours',
'offre follow gagnant',
'concours pour gagner',
'gagner rt',
'Gagnez rt follow',
'RT follow',
'concours rt like',
'concours rt fav',
'RT tweet Follow',
'concours rt follow',
'rt follow tas',
'rt follow tirage au sort',
'rt follow gagner',
'rt follow commente',
'rt suivre concours',
'rt suivez concours',
'rt suivre tirage au sort',
'rt suivre tas',
'concours remporter',
'remporter rt',
'concours tas le',
'concours résultats le rt',
'tirage au sort concours',
'concours résultat le rt'
];
$k = array_rand($search);
$phrase = $search[$k];
$date = Carbon::now()->subDays(2)->format('Y-m-d');
$url = 'https://nitter-myx.fly.dev/search?f=tweets&q='.urlencode('min_replies:100 '.$phrase).'&e-nativeretweets=on&e-replies=on&&since='.$date;
$client = new HttpBrowser(HttpClient::create(['verify_peer' => false, 'verify_host' => false, 'timeout' => '60']));
// Création des informations d'authentification
$username = 'MyX';
$password = '@Gaudin95';
$credentials = base64_encode("$username:$password");
// Ajout des informations d'authentification à l'en-tête de la demande HTTP
$client->setServerParameter('HTTP_AUTHORIZATION', 'Basic ' . $credentials);
$client->setServerParameter('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36');
$crawler = $client->request('GET', $url);
$crawler->filterXPath('//div[@class="timeline-item "]')->each(function ($node) {
$id = ($node->filterXPath('//*[@class="tweet-link"]'))->attr('href');
$created_at = ($node->filterXPath('//span[@class="tweet-date"]/a'))->attr('title');
$text = ($node->filterXPath('//*[@class="tweet-content media-body"]'))->text();
$screen = ($node->filterXPath('//a[@class="username"]'))->text();
$fullname = ($node->filterXPath('//a[@class="fullname"]'))->text();
$imageNode = $node->filterXPath('//a[@class="still-image"]');
$nbretweet = ($node->filterXPath('//*[@class="tweet-stat"][2]'))->text();
$nbretweet = str_replace(',', '', $nbretweet);
$nblike = ($node->filterXPath('//*[@class="tweet-stat"][4]'))->text();
$nblike = str_replace(',', '', $nblike);
$nbreply = ($node->filterXPath('//*[@class="tweet-stat"][1]'))->text();
$nbreply = str_replace(',', '', $nbreply);
//Modifications
if ($imageNode->count() > 0) {
$picture = $imageNode->attr('href');
$picture = urldecode($picture);
$picture = str_replace('/pic/orig/', 'https://pbs.twimg.com/', $picture);
} else {
$picture = null;
}
$screen = str_replace('@', '', $screen);
$id = str_replace('/' . $screen . '/status/', '', $id);
$id = str_replace('#m', '', $id);
$contest = Contest::where('tweetid', $id)->first();
$fake = Block::where('screen_name', $screen)->first();
$containsBlacklistedWord = preg_match('/' . implode('|', array_map('preg_quote', config('twitter.giveaway_to_blacklist'), ['/'])) . '/i', $text) === 1;
if (!$contest && !$fake && $nbretweet > 1000 && $containsBlacklistedWord !== true) {
$regex_detect_rts =
[
"/\bRT\b/",
"/RETWEET/i",
"/REPUBL/i",
"/REPOST/i",
"/LIKE/i",
"/MENTION/i",
];
foreach ($regex_detect_rts as $regex_detect_rt) {
//if (strstr($string, $url)) { // mine version
preg_match($regex_detect_rt, $text, $invites);
if (isset($invites[0])) {
$rt = true;
}
}
//On verifie que si RT
if (isset($rt)) {
$inputs = array();
//On recherche la date de fin du concours
$date = $this->getDate($text);
if ($date != null) {
$fin = $date;
} else {
$fin = $this->getTwitterDate($created_at);
}
//On recherche la date de fin du concours
if ($fin >= Carbon::now()->format('Y-m-d')) {
Contest::create([
'name' => $fullname,
'screen' => $screen,
'description' => $text,
'url' => 'https://x.com/' . $screen . '/status/' . $id,
'picture' => $picture,
'tweetid' => $id,
'fin' => $fin,
'nbretweet' => $nbretweet,
'nblike' => $nblike,
'nbreply' => $nbreply,
]);
}
}
}
});
$reponse = $client->getResponse();
var_dump($reponse);
echo 'Fait !';
}
public function import()
{
$response = Http::get('https://rtandfollow.com/apibot');
$tweets = $response->json();
foreach($tweets as $status) {
$tweetid = $status['tweetid'];
$screen_name = $status['organizer']['screen_name'];
$text = $status['description'];
$concours = Contest::where('tweetid', $tweetid)->first();
$blocking = Block::where('screen_name', $screen_name)->first();
$containsBlacklistedWord = preg_match('/' . implode('|', array_map('preg_quote', config('twitter.giveaway_to_blacklist'), ['/'])) . '/i', $text) === 1;
//On verifie que le concours n'est pas dans la BDD ou que l'utilisateur n'est pas bloqué
if (empty($concours) and empty($blocking) and $containsBlacklistedWord !== true) {
//On recherche la date de fin du concours
$fin = $status['fin'];
if ($fin >= Carbon::now()->format('Y-m-d')) {
Contest::create([
'name' => $status['organizer']['name'],
'screen' => $screen_name,
'description' => $text,
'url' => $status['url'],
'picture' => '',
'tweetid' => $tweetid,
'fin' => $fin,
'nbretweet' => $status['nbretweet'],
'nblike' => $status['nblike'],
'nbreply' => $status['nbreply'],
]);
}
}
}
}
public function getOrganizer($screen)
{
$organiser = Organizer::where('screen_name', $screen)->first();
if ($organiser){
return $organiser->id;
}else
{
$client = new HttpBrowser(HttpClient::create(['verify_peer' => false, 'verify_host' => false, 'timeout' => '60']));
// Création des informations d'authentification
$username = 'autokdo';
$password = '@Gaudin95';
$credentials = base64_encode("$username:$password");
// Ajout des informations d'authentification à l'en-tête de la demande HTTP
$client->setServerParameter('HTTP_AUTHORIZATION', 'Basic ' . $credentials);
$client->setServerParameter('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36');
$crawler = $client->request('GET', 'https://nitter-autokdo.fly.dev/'.$screen);
try{
$name = $crawler->filterXPath('//*[@class="profile-card-fullname"]')->text();
$description = $crawler->filterXPath('//*[@class="profile-bio"]')->text();
$profileUrl = $crawler->getUri();
$parsedUrl = parse_url($profileUrl);
$baseTwitterUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'];
$image = $crawler->filterXPath('//meta[@property="og:image"]')->attr('content');
$url = str_replace("http://nitter-autokdo.fly.dev/pic/", "", $image);
$url = urldecode($url);
$url = 'https://'.$url;
$response = Http::get($url);
$contents = $response->body();
// Utilisation de getimagesize pour obtenir les informations sur l'image
$imageInfo = getimagesizefromstring($contents);
if ($imageInfo === false) {
$filename = 'icon-96x96.png';
}
$format = image_type_to_extension($imageInfo[2], false);
$filename = uniqid() . '.' . $format;
// Stocker l'image dans le répertoire 'ads' du stockage
Storage::put('/public/logo/'.$filename, $contents);
$organiser = Organizer::create([
'name' => $name,
'screen_name' => $screen,
'description' => $description,
'logo' => $filename,
'url' => 'https://twitter.com/'.$screen,
]);
return $organiser->id;
} catch (\Exception $e) {
dd($e);
}
}
}
private function getCategorie($data)
{
$client = new HttpBrowser(HttpClient::create(['verify_peer' => false, 'verify_host' => false, 'timeout' => '60']));
$client->request('GET', 'https://api.uclassify.com/v1/twittercontests/categories/classify/?readKey=c7ivTcoN2ycU&text='.$data);
$json = $client->getResponse()->getContent();
$array = json_decode($json,true);
$laravelArray = collect($array);
$laravelArray = $laravelArray->sortDesc();
$value = $laravelArray->first();
if($value < '0.5'){
$categorie = '20';
}
else{
$cat = $laravelArray->keys()->first();
if($cat == 'argent'){
$categorie = '1';
}elseif($cat == 'beaute'){
$categorie = '2';
}elseif($cat == 'console'){
$categorie = '3';
}elseif($cat == 'cuisine'){
$categorie = '4';
}elseif($cat == 'dvd'){
$categorie = '5';
}elseif($cat == 'enfant'){
$categorie = '6';
}elseif($cat == 'goodies'){
$categorie = '7';
}elseif($cat == 'invitation'){
$categorie = '8';
}elseif($cat == 'livre'){
$categorie = '9';
}elseif($cat == 'maison'){
$categorie = '10';
}elseif($cat == 'mode'){
$categorie = '11';
}elseif($cat == 'pc'){
$categorie = '12';
}elseif($cat == 'sport'){
$categorie = '13';
}elseif($cat == 'telephone'){
$categorie = '14';
}elseif($cat == 'voiture'){
$categorie = '15';
}elseif($cat == 'voyage'){
$categorie = '16';
}else{
$categorie = '20';
}
}
return $categorie;
}
private function getDate($string) {
// Pattern pour détecter les dates au format JJ/MM ou JJ.MM
$pattern_jjmm = '/\b(\d{1,2})(\/|\.)\d{1,2}\b/';
// Pattern pour détecter les dates du style "1 août" (ou autre mois en français)
$mois_fr = array(
'janvier', 'février', 'mars', 'avril', 'mai', 'juin',
'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'
);
$pattern_jj_mois_fr = '/\b(\d{1,2}) (' . implode('|', $mois_fr) . ')\b/i';
// Stocker les correspondances dans un tableau
$correspondances = [];
// Chercher les dates au format JJ/MM ou JJ.MM
if (preg_match_all($pattern_jjmm, $string, $matches)) {
$correspondances = array_merge($correspondances, $matches[0]);
}
// Chercher les dates du style "1 août" (ou autre mois en français)
if (preg_match_all($pattern_jj_mois_fr, $string, $matches)) {
// Convertir le mois en format numérique (1 pour janvier, 2 pour février, etc.)
$mois_numerique = array_flip($mois_fr);
foreach ($matches[2] as $index => $mois) {
$matches[0][$index] = $matches[1][$index] . '/' . str_pad($mois_numerique[strtolower($mois)] + 1, 2, '0', STR_PAD_LEFT);
}
$correspondances = array_merge($correspondances, $matches[0]);
}
// Vérifier s'il y a des dates détectées
if (empty($correspondances)) {
return ""; // Retourne une chaîne vide si aucune date n'est trouvée
}
// Récupérer la dernière date détectée
$derniere_date = end($correspondances);
// Convertir la dernière date au format "Y-m-d" (année-mois-jour)
if (strpos($derniere_date, '/') !== false) {
// Format JJ/MM
list($jour, $mois) = explode('/', $derniere_date);
$annee = date('Y');
} elseif (strpos($derniere_date, '.') !== false) {
// Format JJ.MM
list($jour, $mois) = explode('.', $derniere_date);
$annee = date('Y');
} else {
return ""; // Cas inattendu (ne devrait pas se produire)
}
// Convertir en date avec gestion des erreurs (ex. : février 30)
try {
$date_convertie = date('Y-m-d', strtotime("$annee-$mois-$jour"));
} catch (Exception $e) {
return ""; // Retourne une chaîne vide si la conversion échoue
}
return $date_convertie;
}
private function getTwitterDate($text)
{
// Utilisez une expression régulière pour extraire toutes les dates
$pattern = '/(\w{3} \d{1,2}, \d{4})/';
preg_match_all($pattern, $text, $matches);
if (!empty($matches[1])) {
// Récupérer la dernière date trouvée
$lastDateString = end($matches[1]);
// Analyse de la date
$date = Carbon::createFromFormat('M d, Y', $lastDateString);
// Obtenez la date au format Y-m-d
$formattedDate = $date->addDays(1)->format('Y-m-d');
return $formattedDate;
} else {
// Retourne la date actuelle +1 jour si aucune date n'est trouvée
return Carbon::now()->addDays(1)->format('Y-m-d');
}
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers;
use App\Models\Contest;
use Artesaos\SEOTools\Facades\SEOTools;
class HomeController extends Controller
{
public function index()
{
SEOTools::setTitle('Liste des concours');
return view('index');
}
public function history()
{
$contests = Contest::where('participated',true)->orderby('updated_at','desc')->paginate(20);
SEOTools::setTitle('Mon historique');
return view('history', compact('contests'));
}
}