马斯克不讲德武德,xAI免费结束
真不知道老马怎么想的,从乌克兰到现在的xAI,总是弄些很奇怪的言行和举动。
没做到承诺的永久也就算了,但一点提前量都没有,5月中旬来宣布6/1停止使用,这真的过份了。
我们一介草尼能怎么样呢?删号走人!
真不知道老马怎么想的,从乌克兰到现在的xAI,总是弄些很奇怪的言行和举动。
没做到承诺的永久也就算了,但一点提前量都没有,5月中旬来宣布6/1停止使用,这真的过份了。
我们一介草尼能怎么样呢?删号走人!
一直觉得Gemini非常垃圾,前些天Google放水,这不骗了一个Advance来用嘛,以为会比免费版更好点,结果用下来还是一团屎。
新闻/软文是天天看到秒天秒地秒空气,但每次用,都是各个AI里面最差的,而且是差得离谱那种。在AI时代大潮中,Google真的败了。
今天要解决docker和iptables冲突的问题,所以,问了一堆的AI怎么解决这问题。很遗憾,没有一个能解决,这点我认了。。这问题确实有难度,stack overflow上我看到鬼佬也是弄了很久最终放弃。
但是,别的AI,包括GPT,包括Claude,包括Grok,包括DeepSeek都努力想帮我解决问题,至少态度很好。唯独Gemini,不知道是触动了它的哪个高潮点,它在回答了一半之后,直接退行清除掉先前回答的内容,然后生硬的拒绝回答。 用过DeepSeek的人都知道,问它zz敏感问题就是这样。
问题是,我只是问iptables规则啊?想啥呢?
用过很多年GCP了,熟知他的永久免费机计费规则:
特定的三个区域,俄勒冈啥的
E2-MICRO
30G标准永久磁盘
标准网络层级
以前也用得好好的,一直每月0费用,直到,上个月底删除了机器然后再新开了机器。当时发现开机界面变了,我很小心的还是按照上面的规则来开机,咱老司机了,小事对吧? 很不幸,翻车了!哇哦,一个星期居然欠了4分钱。
几分钱不多不是付不起,咱不是非洲难民,但这给人挖坑让人不爽啊!
帐单看上去,应该是开机器的时候自动默认给开了一个多区域的备份啥吧,懒得研究了,我不用了,惹不起躲得起。
另外,我就欠了4分钱,一没扣到,至于就那么气势汹汹的就直接关闭帐号么?谁家不是都会通知一下给几天宽限期?gcp这么猴急干嘛。
后续,忍不住,还是研究了一下,应该是开机时操作需要多一个选择点:
数据安全->无快照
人活得这么风光不容易也不虚一生了。
Rivers do not drink their own waters; trees do not eat their own fruit; the sun does not shine on itself and flowers do not spread their fragrance for themselves. Living for others is a rule of nature. We are all born to help each other. No matter how difficult it is...Life is good when you are happy; but much better when others are happy because of you!
-- Pope Francis
昨天突然发现了dht爬虫可以用bitmagnet自部署,欣喜若狂啊,以前有什么手撕包菜什么的,不过早就不行了。
为什么自部署?因为数据库在自己这里啊,想怎么查询怎么查询,能精准的找到自己的需要。
连夜部署好bitmagnet,然后再手搓好api和页面,不错不错。。。 因为过于那个,demo不敢放了,只放一下代码吧。
api的功能是在数据库中随机查找包含中文(不允许日文平片假名),然后包含的压缩文件大小比例不超过50%的。
后面两个要求我不解释,我只解释一下随机。。知识爆炸文件爆炸,爆炸到连关键词都想不出来了,所以,随机随机,也许有喜欢的。 🙂🙂
package main
import (
"database/sql"
"log"
"net/http"
"strings"
"github.com/gin-gonic/gin"
_ "github.com/lib/pq"
)
type Torrent struct {
InfoHash string `json:"info_hash"`
SizeGB float64 `json:"size_gb"`
Name string `json:"name"`
}
func main() {
r := gin.Default()
r.GET("/api/rantorrents", handleGetTorrents)
if err := r.Run(":8000"); err != nil {
log.Fatal(err)
}
}
func handleGetTorrents(c *gin.Context) {
db, err := sql.Open("postgres", "host=127.0.0.1 port=5432 dbname=bitmagnet user=postgres password=postgres sslmode=disable")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "db error"})
return
}
defer db.Close()
const query = `
SELECT encode(info_hash, 'hex') AS info_hash, size, name
FROM torrents
WHERE name ~ '[\u4e00-\u9fff]'
AND name !~ '[\u3040-\u309f]'
AND name !~ '[\u30a0-\u30ff]'
ORDER BY RANDOM()
LIMIT 100;
`
rows, err := db.Query(query)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "query fail"})
return
}
defer rows.Close()
var results []Torrent
compressedExts := []string{".zip", ".rar", ".7z", ".tar", ".gz", ".bz2"}
for rows.Next() {
var infoHash, name string
var size int64
if err := rows.Scan(&infoHash, &size, &name); err != nil {
continue
}
var totalFileSize int64
var compressedSize int64
filesQuery := `
SELECT path, size
FROM torrent_files
WHERE info_hash = decode($1, 'hex')
`
fileRows, err := db.Query(filesQuery, infoHash)
if err != nil {
continue
}
for fileRows.Next() {
var path string
var fileSize int64
if err := fileRows.Scan(&path, &fileSize); err != nil {
continue
}
totalFileSize += fileSize
ext := strings.ToLower(path)
for _, suffix := range compressedExts {
if strings.HasSuffix(ext, suffix) {
compressedSize += fileSize
break
}
}
}
fileRows.Close()
if totalFileSize == 0 || float64(compressedSize)/float64(totalFileSize) > 0.5 {
continue }
t := Torrent{
InfoHash: infoHash,
SizeGB: float64(size) / (1024 * 1024 * 1024),
Name: name,
}
results = append(results, t)
if len(results) >= 20 {
break
}
}
c.JSON(http.StatusOK, results)
}
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>随机磁链</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
margin: 0;
font-family: sans-serif;
background: #f5f5f5;
display: flex;
flex-direction: column;
align-items: center;
}
.button {
margin: 10px;
padding: 8px 16px;
background: #3498db;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
}
.list {
width: 100%;
max-width: 800px;
padding: 10px;
box-sizing: border-box;
}
.torrent {
background: #fff;
margin: 6px 0;
padding: 10px;
border-radius: 6px;
box-shadow: 0 1px 4px rgba(0,0,0,0.1);
}
.name {
font-size: 15px;
cursor: pointer;
word-break: break-word;
}
.copied {
font-size: 12px;
color: green;
margin-left: 10px;
display: none;
}
@media (max-width: 600px) {
.name {
font-size: 14px;
}
}
</style>
</head>
<body>
<button class="button" onclick="loadTorrents(false)">🔄 刷新</button>
<div class="list" id="list"></div>
<script>
let loading = false;
async function loadTorrents(append = true) {
if (loading) return;
loading = true;
try {
const res = await fetch('/api/rantorrents');
const data = await res.json();
console.log('收到的数据:', data); // 调试:输出数据检查
const list = document.getElementById("list");
if (!append) list.innerHTML = "";
if (data.length === 0) {
console.log('没有数据!');
return;
}
data.forEach(item => {
const div = document.createElement("div");
div.className = "torrent";
const name = document.createElement("div");
name.className = "name";
// 修复size字段,确保是有效的数字,并且以GB为单位显示
const sizeInGB = item.size_gb ? item.size_gb.toFixed(2) : "0.00";
name.textContent = `[${sizeInGB} GB] ${item.name}`;
const copied = document.createElement("span");
copied.className = "copied";
copied.textContent = "✔ 已复制";
const magnet = `magnet:?xt=urn:btih:${item.info_hash}`;
name.onclick = async () => {
try {
await navigator.clipboard.writeText(magnet);
copied.style.display = "inline";
setTimeout(() => (copied.style.display = "none"), 1500);
} catch (err) {
alert("复制失败:" + err);
}
};
div.appendChild(name);
div.appendChild(copied);
list.appendChild(div);
});
// 限制最多保留 100 条
while (list.children.length > 100) {
list.removeChild(list.firstChild);
}
} catch (err) {
console.error("加载失败:", err);
}
loading = false;
}
// 初始加载
loadTorrents();
// 无限滚动:接近底部时加载更多
window.addEventListener("scroll", () => {
if ((window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 200)) {
loadTorrents(true);
}
});
</script>
</body>
</html>