# Contributing to NewsNow

Thank you for considering contributing to NewsNow! This document provides guidelines and instructions for contributing to the project.

## Adding a New Source

NewsNow is built to be easily extensible with new sources. Here's a step-by-step guide on how to add a new source:

### 1. Create a Feature Branch

Always create a feature branch for your changes:

```bash
git checkout -b feature-name
```

For example, to add a Bilibili hot video source:

```bash
git checkout -b bilibili-hot-video
```

### 2. Register the Source in Configuration

Add your new source to the source configuration in `/shared/pre-sources.ts`:

```typescript
"bilibili": {
  name: "哔哩哔哩",
  color: "blue",
  home: "https://www.bilibili.com",
  sub: {
    "hot-search": {
      title: "热搜",
      column: "china",
      type: "hottest"
    },
    "hot-video": {  // Add your new sub-source here
      title: "热门视频",
      column: "china",
      type: "hottest"
    }
  }
};
```

For a completely new source, add a new top-level entry:

```typescript
"newsource": {
  name: "New Source",
  color: "blue",
  home: "https://www.example.com",
  column: "tech", // Pick an appropriate column
  type: "hottest" // Or "realtime" if it's a news feed
};
```

### 3. Implement the Source Fetcher

Create or modify a file in the `/server/sources/` directory. If your source is related to an existing one (like adding a new Bilibili sub-source), modify the existing file:

```typescript
// In /server/sources/bilibili.ts

// Define interface for API response
interface HotVideoRes {
  code: number;
  message: string;
  ttl: number;
  data: {
    list: {
      aid: number;
      // ... other fields
      bvid: string;
      title: string;
      pubdate: number;
      desc: string;
      pic: string;
      owner: {
        mid: number;
        name: string;
        face: string;
      };
      stat: {
        view: number;
        like: number;
        reply: number;
        // ... other stats
      };
    }[];
  };
}

// Define source getter function
const hotVideo = defineSource(async () => {
  const url = "https://api.bilibili.com/x/web-interface/popular";
  const res: HotVideoRes = await myFetch(url);

  return res.data.list.map((video) => ({
    id: video.bvid,
    title: video.title,
    url: `https://www.bilibili.com/video/${video.bvid}`,
    pubDate: video.pubdate * 1000,
    extra: {
      info: `${video.owner.name} · ${formatNumber(video.stat.view)}观看 · ${formatNumber(video.stat.like)}点赞`,
      hover: video.desc,
      icon: proxyPicture(video.pic),
    },
  }));
});

// Helper function for formatting numbers
function formatNumber(num: number): string {
  if (num >= 10000) {
    return `${Math.floor(num / 10000)}w+`;
  }
  return num.toString();
}

// Export the source
export default defineSource({
  bilibili: hotSearch,
  "bilibili-hot-search": hotSearch,
  "bilibili-hot-video": hotVideo, // Add your new source here
});
```

For completely new sources, create a new file in `/server/sources/` named after your source (e.g., `newsource.ts`).

### 4. Regenerate Source Files

After adding or modifying source files, run the following command to regenerate the necessary files:

```bash
npm run presource
```

This will update the `sources.json` file and any other necessary configuration.

### 5. Test Your Changes

Start the development server to test your changes:

```bash
npm run dev
```

Access the application in your browser and ensure that your new source is appearing and working correctly.

### 6. Commit Your Changes

Once everything is working, commit your changes:

```bash
git add .
git commit -m "Add new source: source-name"
```

### 7. Create a Pull Request

Push your changes to your fork and create a pull request against the main repository:

```bash
git push origin feature-name
```

## Source Structure

### NewsItem Structure

Each source should return an array of objects that conform to the `NewsItem` interface:

```typescript
interface NewsItem {
  id: string | number; // Unique identifier for the item
  title: string; // Title of the news item
  url: string; // URL to the full content
  mobileUrl?: string; // Optional mobile-specific URL
  pubDate?: number | string; // Publication date
  extra?: {
    hover?: string; // Text to display on hover
    date?: number | string; // Formatted date
    info?: false | string; // Additional information
    diff?: number; // Time difference
    icon?:
      | false
      | string
      | {
          // Icon for the item
          url: string;
          scale: number;
        };
  };
}
```

## Code Style

Please follow the existing code style in the project. The project uses TypeScript and follows modern ES6+ conventions.

## License

By contributing to this project, you agree that your contributions will be licensed under the project's license.
