diff options
Diffstat (limited to 'tool/mastodonwch')
-rw-r--r-- | tool/mastodonwch/README.md | 105 | ||||
-rw-r--r-- | tool/mastodonwch/cron.php | 80 | ||||
-rw-r--r-- | tool/mastodonwch/index.php | 136 |
3 files changed, 321 insertions, 0 deletions
diff --git a/tool/mastodonwch/README.md b/tool/mastodonwch/README.md new file mode 100644 index 00000000..0740a887 --- /dev/null +++ b/tool/mastodonwch/README.md @@ -0,0 +1,105 @@ +### Shared on Mastodon + +Who is sharing most Cloudflare links to other people? +Oh, it's you? + +Congratulations, you are ranked in the top 50 of... + + + +(_Sarcasm? Of course. Stop sharing CF links already!_) + +What you can do? Tell them to stop using Cloudflare! + + +### Some public reaction + +``` +'your little protest bot is making people upset, +and i'm worried it might cause people to defederate from the instance, +please tone it down' + +We need a new word for describing how fucked up this is, +insanity just isn't doing it anymore. + +No shit it makes people upset *that's the fucking point* +``` +-- [Jeff Cliff](http://qhtn4w2q36dojls2.onion/) + + +``` +The bot doesn't care about you personally. +It's doing a public service for your readers, who you otherwise sent into +a netneutrality-hostile privacy-abusive walled-garden. + +It's to protect them so they are warned and have a trustworthy link to follow. +``` +-- [resist1984](https://social.privacytools.io/@resist1984) + + +``` +It doesn't matter if it is still online if I can't access it... +so the bot is appreciated. +``` +-- [Thufie](https://social.pixie.town/@thufie) + + +### Code + +- [index.php](index.php): Main website to show the result +- [cron.php](cron.php): Use it with your cronjob + + +### Database + +- toot_cfsaid: Tweet URL which CF link was observed +``` +id varchar(40) UNIQUE +who varchar(80) INDEX +url varchar(200) INDEX +ym int(6) INDEX +``` + +- toot_notcf_fqdn: Unknown FQDN which was not listed as Cloudflare +``` +fqdn varchar(200) UNIQUE +dl int(1) INDEX +``` + +- toot_scanned: To make sure not to analyze same tweet again +``` +id varchar(40) UNIQUE +who varchar(80) INDEX +iscf int(1) INDEX +ym int(6) INDEX +``` + +- toot_sharefqdn: Just for counting FQDN +``` +id varchar(40) UNIQUE +fqdn varchar(200) INDEX +ym int(6) INDEX +``` + + +### Live demo + +If you want to see this in action: [Onion](http://stopcloudflare@avrynpc2q7pknqa3ucf5tvjcwad5nxvxgwnzvl2b6dx6uo4f7nc7zzqd.onion/mastodon/) + + + +### Live API + +`http://(onion)/mastodon/?who=a&json` + +`who`: +- `a`, Show Top 100 (Shared any links) +- `c`, Show Top 100 (Shared Cloudflare links) +- `f`, Show Top 100 (Shared FQDN) +- `u`, About Mastodon Users +- `s`, About Mastodon Servers + +Example: +`curl -x socks5h://127.0.0.1:9050 -G -H "Authorization: Basic c3RvcGNsb3VkZmxhcmU6" "http://-----.onion/mastodon/" -d "who=c" -d "json"` + +> `[{"rank":1,"who":"xxx","toots":"xxx"},{"rank":2,...`
\ No newline at end of file diff --git a/tool/mastodonwch/cron.php b/tool/mastodonwch/cron.php new file mode 100644 index 00000000..b6a26f67 --- /dev/null +++ b/tool/mastodonwch/cron.php @@ -0,0 +1,80 @@ +<?php +ignore_user_abort(true); +set_time_limit(120); +$toots = []; +$mastodon_servers = ['your.server.fqdn' => 'https://your.server.fqdn/write_this_block_yourself', 'yours2.fqdn' => 'https://...']; +shuffle_assoc($mastodon_servers); +$date_ym = gmdate('Ym'); +$sqlme = @new mysqli('localhost', 'sseeccrreett', 'sseeccrreett', 'sseeccrreett'); +if ($sqlme->connect_errno) +{ + exit; +} +foreach ($mastodon_servers as $svF => $svU) +{ + $got = @json_decode(wget($svU) , true); + if (!is_array($got) || count($got) < 10 || !isset($got[0])) + { + continue; + } + foreach ($got as $g) + { + if (!isset($g['url']) || !preg_match("/write_this_block_yourself/", $g['url'])) + { + continue; + } + if (!isset($g['content']) || strlen($g['content']) < 8) + { + continue; + } + if (!isset($g['account']) || !isset($g['account']['acct']) || !preg_match("/write_this_block_yourself/", $g['account']['acct'])) + { + continue; + } + if (strpos($g['account']['acct'], '@') === false) + { + $g['account']['acct'] = $g['account']['acct'] . '@' . $svF; + } + $txt = array_unique(array_filter(array_map(function ($l) + { + $isURL = (preg_match("/write_this_block_yourself/", $l) && !preg_match("/write_this_block_yourself/", $l)) ? true : false; + return $isURL ? explode('/', explode('://', $l, 2) [1], 2) [0] : ''; + } + , explode('"', strip_tags($g['content'], '<a>'))))); + if (count($txt) == 0) + { + continue; + } + $cfFound = 0; + foreach ($txt as $fqdn) + { + $tmp_id2 = sha1($g['url'] . ';' . $fqdn); + $junk = $sqlme->query("INSERT IGNORE INTO toot_sharefqdn (id,fqdn,ym) VALUES ('{$tmp_id2}','{$fqdn}','{$date_ym}');"); + if (is_known_cf(get_domainname($fqdn) [1])) + { + $cfFound = 1; + } + else + { + $junk = $sqlme->query("INSERT IGNORE INTO toot_notcf_fqdn (fqdn,dl) VALUES ('{$fqdn}','0');"); + } + } + $toots[sha1($g['url']) ] = [$g['account']['acct'], $g['url'], $cfFound]; + } +} +foreach ($toots as $k => $v) +{ + $junk = $sqlme->query("INSERT IGNORE INTO toot_scanned (id,who,iscf,ym) VALUES ('{$k}','{$v[0]}','{$v[2]}','{$date_ym}');"); + if ($v[2] == 1) + { + $junk = $sqlme->query("INSERT IGNORE INTO toot_cfsaid (id,who,url,ym) VALUES ('{$k}','{$v[0]}','{$v[1]}','{$date_ym}');"); + } +} +if (gmdate('G') == 0) +{ + $date_ym = gmdate('Ym', strtotime('7 months ago')); + $junk = $sqlme->query("DELETE FROM toot_scanned WHERE ym = '{$date_ym}';"); + $junk = $sqlme->query("DELETE FROM toot_cfsaid WHERE ym = '{$date_ym}';"); + $junk = $sqlme->query("DELETE FROM toot_sharefqdn WHERE ym = '{$date_ym}';"); +} +file_put_contents('/onion/sseeccrreett/data/mastodon.toot.scan', '');
\ No newline at end of file diff --git a/tool/mastodonwch/index.php b/tool/mastodonwch/index.php new file mode 100644 index 00000000..39503053 --- /dev/null +++ b/tool/mastodonwch/index.php @@ -0,0 +1,136 @@ +<?php +$sqlme = @new mysqli('localhost', 'sseeccrreett', 'sseeccrreett', 'sseeccrreett'); +if ($sqlme->connect_errno) +{ + exit; +} +$count_all = - 1; +if ($r = $sqlme->query("SELECT count(id) FROM toot_scanned;")) +{ + $rr = mysqli_fetch_assoc($r); + $r->free(); + $count_all = $rr['count(id)']; +} +$count_cf = - 1; +if ($r = $sqlme->query("SELECT count(id) FROM toot_scanned WHERE iscf=1;")) +{ + $rr = mysqli_fetch_assoc($r); + $r->free(); + $count_cf = $rr['count(id)']; +} +if ($count_all == - 1 || $count_cf == - 1) +{ + exit; +} +$count_acpct = round(($count_cf * 100) / $count_all, 2); +$count_all = number_format($count_all); +$count_cf = number_format($count_cf); +$count_waitask = - 1; +if ($r = $sqlme->query("SELECT count(fqdn) FROM toot_notcf_fqdn WHERE dl=0;")) +{ + $rr = mysqli_fetch_assoc($r); + $r->free(); + $count_waitask = $rr['count(fqdn)']; +} +$count_waitask = number_format($count_waitask); +$lastuptime = humanTiming(filemtime('/onion/sseeccrreett/data/mastodon.toot.scan')); +$var_who = htmlspecialchars($_GET['who'], ENT_QUOTES); +$resultHTML = ''; +if (write_this_block_yourself) +{ + $var_who = ''; +} +if (preg_match("/write_this_block_yourself/", $var_who)) +{ + $resultHTML .= '<br><table border=1>'; + $person_a = 0; + if ($r = $sqlme->query("SELECT count(id) FROM toot_scanned WHERE who='{$var_who}';")) + { + $rr = mysqli_fetch_assoc($r); + $r->free(); + $person_a = $rr['count(id)']; + } + $person_b = 0; + if ($r = $sqlme->query("SELECT count(id) FROM toot_scanned WHERE who='{$var_who}' AND iscf=1;")) + { + $rr = mysqli_fetch_assoc($r); + $r->free(); + $person_b = $rr['count(id)']; + } + $person_c = round(($person_b * 100) / $person_a, 2); + if (is_nan($person_c)) + { + $person_c = 0; + } + $person_a = number_format($person_a); + $person_b = number_format($person_b); + $resultHTML .= "<tr><th>About</th><th>{$var_who}</th></tr>"; + $resultHTML .= "<tr><td>Toots has links</td><td>{$person_a}</td></tr>"; + $resultHTML .= "<tr><td>⮡ Toots has Cloudflare link</td><td>{$person_b} [<i>{$person_c}</i>%]</td></tr>"; + $resultHTML .= "<tr><td> </td><td>Detected (LIMIT 100)</td></tr>"; + if ($r = $sqlme->query("SELECT url FROM toot_cfsaid WHERE who='{$var_who}' LIMIT 100;")) + { + while ($row = mysqli_fetch_assoc($r)) + { + $vurl = htmlspecialchars($row['url'], ENT_QUOTES); + $resultHTML .= "<tr><td></td><td><a href=\"{$vurl}\" target=\"_blank\">{$vurl}</a></td></tr>"; + } + } + $resultHTML .= '</table>'; +} +elseif ($var_who == 'a') +{ + $resultHTML .= '<br><table border=1><tr><th>Shared any links</th><th>Toots</th></tr>'; + if ($r = $sqlme->query("SELECT who,count(*) as count FROM toot_scanned GROUP BY who ORDER BY count DESC LIMIT 100;")) + { + while ($row = mysqli_fetch_assoc($r)) + { + $rcount = number_format($row['count']); + $resultHTML .= "<tr><td><a href=\"./?who={$row['who']}\">{$row['who']}</a></td><td>{$rcount}</td></tr>"; + } + } + $resultHTML .= '</table>'; +} +elseif ($var_who == 'c') +{ + $resultHTML .= '<br><table border=1><tr><th>Shared Cloudflare links</th><th>Toots</th></tr>'; + if ($r = $sqlme->query("SELECT who,count(*) as count FROM toot_scanned WHERE iscf=1 GROUP BY who ORDER BY count DESC LIMIT 100;")) + { + while ($row = mysqli_fetch_assoc($r)) + { + $rcount = number_format($row['count']); + $resultHTML .= "<tr><td><a href=\"./?who={$row['who']}\">{$row['who']}</a></td><td>{$rcount}</td></tr>"; + } + } + $resultHTML .= '</table>'; +} +elseif ($var_who == 'f') +{ + $resultHTML .= '<br><table border=1><tr><th>Shared FQDN</th><th>Cloudflare</th><th>Found in Toots</th></tr>'; + if ($r = $sqlme->query("SELECT fqdn,count(*) as count FROM toot_sharefqdn GROUP BY fqdn ORDER BY count DESC LIMIT 50;")) + { + while ($row = mysqli_fetch_assoc($r)) + { + $rcount = number_format($row['count']); + $riscf = is_known_cf(get_domainname($row['fqdn']) [1]) ? '<font color="red">Yes</font>' : 'No'; + $resultHTML .= "<tr><td>{$row['fqdn']}</td><td>{$riscf}</td><td>{$rcount}</td></tr>"; + } + } + $resultHTML .= '</table>'; +} +else +{ + $resultHTML .= '<ul><li> <a href="./?who=a">Show Top 100 (Shared any links)</a></li>'; + $resultHTML .= '<li> <a href="./?who=c">Show Top 100 (Shared Cloudflare links)</a></li>'; + $resultHTML .= '<li> <a href="./?who=f">Show Top 50 (Shared FQDN)</a></li>'; + $resultHTML .= '<li> <a href="#" onclick="location.href=\'./?who=\'+(prompt(\'user@example.com\')||\'\');">Search by Mastodon ID</a></li></ul>'; +} +$finalpage = <<<HTMLRESULT +<html><title>Shared on Mastodon</title><br><br><div> +[ <a href="./">INDEX</a> ] Update <i>{$lastuptime} ago</i><br> +<b>Toots has links</b>: {$count_all}<br> +⮡ <b>Toots has Cloudflare link</b>: {$count_cf} [<i>{$count_acpct}</i>%]<br> +<b>Pending Investigation</b>: {$count_waitask}<br> +<hr>{$resultHTML}</div></html> +HTMLRESULT; +echo (str_replace("\n", '', $finalpage));
\ No newline at end of file |