Giter VIP home page Giter VIP logo

usenet's Introduction

Usenet

A library for working with Usenet. It offers:

  • an NNTP client
  • an NZB file parser, builder and writer
  • a yEnc encoder and decoder

It is mainly focused on keeping memory usage low. Server responses can be enumerated as they come in. Binary messages will be encoded to yEnc format streaming and yEnc-encoded data will be decoded to binary data streaming.

The NNTP client is compliant with RFC 2980, RFC 3977, RFC 4643 and RFC 6048.

Build status

Getting Started

Install Nuget package:

PM> Install-Package Usenet

Examples

Connect to Usenet server:

var client = new NntpClient(new NntpConnection());
await client.ConnectAsync(hostname, port, useSsl);

Authenticate:

client.Authenticate(username, password)

Retrieve article:

NntpArticleResponse response = client.Article(messageId);
if (response.Success) {
    foreach (string line in response.Article.Body) {
        ...
    }
}

Build an article and post to server:

string messageId = $"{Guid.NewGuid()}@example.net";

NntpArticle newArticle = new NntpArticleBuilder()
    .SetMessageId(messageId)
    .SetFrom("Randomposter <[email protected]>")
    .SetSubject("Random test post #1")
    .AddGroups("alt.test.clienttest", "alt.test")
    .AddLine("This is a message with id " + messageId)
    .AddLine("with multiple lines")
    .Build();

client.Post(newArticle);

Parse an NZB file, download, decode and write the parts streaming to a file:

NzbDocument nzbDocument = NzbParser.Parse(File.ReadAllText(nzbPath));

foreach (NzbFile file in nzbDocument.Files)
{
    foreach (NzbSegment segment in file.Segments)
    {
        // retrieve article from Usenet server
        NntpArticleResponse response = client.Article(segment.MessageId);

        // decode the yEnc-encoded article
        using (YencStream yencStream = YencStreamDecoder.Decode(response.Article.Body))
        {
            YencHeader header = yencStream.Header;

            if (!File.Exists(header.FileName))
            {
                // create file and pre-allocate disk space for it
                using (FileStream stream = File.Create(header.FileName))
                {
                    stream.SetLength(header.FileSize);
                }
            }
            using (FileStream stream = File.Open(
                header.FileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
            {
                // copy incoming parts to file
                stream.Position = header.PartOffset;
                yencStream.CopyTo(stream);
            }
        }
    }
}

Build an NZB document and write to file:

IFileProvider fileProvider = new PhysicalFileProvider(Path.GetFullPath("testdata"));

NzbBuilder builder = new NzbBuilder()
    .AddGroups("alt.test.clienttest")
    .SetMessageBase("random.local")
    .SetPartSize(50_000)
    .SetPoster("random poster <[email protected]>")
    .AddMetaData("title", "Testing upload Pictures.rar");

foreach (string fileName in fileNames)
{
    builder.AddFile(fileProvider.GetFileInfo(fileName));
}

NzbDocument nzbDocument = builder.Build();

using (FileStream file = File.Open("Pictures.nzb"))
using (var writer = new StreamWriter(file, UsenetEncoding.Default))
{
    await writer.WriteNzbDocumentAsync(nzbDocument);
}

Encode the files from an NZB document in yEnc format and upload streaming:

foreach (NzbFile file in nzbDocument.Files)
{
    // open file stream
    IFileInfo fileInfo = fileProvider.GetFileInfo(file.FileName);
    using (Stream stream = fileInfo.CreateReadStream())
    {
        foreach (NzbSegment segment in file.Segments)
        {
            stream.Position = segment.Offset;

            // encode in yEnc format
            IEnumerable<string> encodedBody = YencEncoder.Encode(new YencHeader(
                file.FileName, file.Size, 128, segment.Number, file.Segments.Count,
                segment.Size, segment.Offset), stream);

            // create article
            NntpArticle article = new NntpArticleBuilder()
                .AddGroups(file.Groups)
                .SetMessageId(segment.MessageId)
                .SetFrom(file.Poster)
                .SetSubject(segment.MessageId)
                .SetBody(encodedBody)
                .Build();

            // post article
            client.Post(article);
        }
    }
}

Close connection:

client.Quit();

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

Acknowledgments

This project was heavily inspired by Kristian Hellang's work:

usenet's People

Contributors

keimpema avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.